All of lore.kernel.org
 help / color / mirror / Atom feed
* [Intel-xe] [PATCH 00/12] GSC FW loading
@ 2023-10-27 22:29 Daniele Ceraolo Spurio
  2023-10-27 22:29 ` [Intel-xe] [PATCH 01/12] drm/xe: implement driver initiated function-reset Daniele Ceraolo Spurio
                   ` (15 more replies)
  0 siblings, 16 replies; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe

the GSC (Graphics Security Controller) is the root of trust for content
protection operations (PXP, HDCP), so loading the the GSC FW is a
prerequisite for those features. Loading the FW is required to turn off
the GSC forcewake well (which we must turn on to enable GSCCS idleness)
and therefore allows MC6 entry.

The GSC FW uses 3 separate versions: release, compatibility and
security. The compatibility version is the one that dictates whether the
driver knows how to interface with the binary so that's the one we match
against, but we also fetch the other two for debug information.

The GSCCS is used to both load the FW (via the GSC_FW_LOAD command) and
to send heci packets to it (via the GSC_HECI_PKT command).

Note: the flr patch from Andrzej is being reviewed separately, I've just
included it here because it is a dependency.

Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Cc: John Harrison <john.c.harrison@intel.com>

Andrzej Hajda (1):
  drm/xe: implement driver initiated function-reset

Daniele Ceraolo Spurio (11):
  fixup! drm/xe/guc: Report submission version of GuC firmware
  drm/xe/uc: Rework uC version tracking
  drm/xe/gsc: Introduce GSC FW
  drm/xe/gsc: Parse GSC FW header
  drm/xe/gsc: GSC FW load
  drm/xe/gsc: Implement WA 14015076503
  drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload
  drm/xe/gsc: Add an interface for GSC packet submissions
  drm/xe/gsc: Query GSC compatibility version
  drm/xe/gsc: Define GSCCS for MTL
  drm/xe/gsc: Define GSC FW for MTL

 drivers/gpu/drm/xe/Makefile                   |   4 +-
 .../gpu/drm/xe/abi/gsc_command_header_abi.h   |  46 +++
 .../gpu/drm/xe/abi/gsc_mkhi_commands_abi.h    |  39 ++
 .../gpu/drm/xe/instructions/xe_gsc_commands.h |  36 ++
 .../gpu/drm/xe/instructions/xe_instr_defs.h   |   1 +
 drivers/gpu/drm/xe/regs/xe_gsc_regs.h         |  39 ++
 drivers/gpu/drm/xe/regs/xe_regs.h             |   7 +
 drivers/gpu/drm/xe/xe_device.c                |  78 ++++
 drivers/gpu/drm/xe/xe_device_types.h          |   3 +
 drivers/gpu/drm/xe/xe_gsc.c                   | 389 ++++++++++++++++++
 drivers/gpu/drm/xe/xe_gsc.h                   |  16 +
 drivers/gpu/drm/xe/xe_gsc_submit.c            | 170 ++++++++
 drivers/gpu/drm/xe/xe_gsc_submit.h            |  30 ++
 drivers/gpu/drm/xe/xe_gsc_types.h             |  39 ++
 drivers/gpu/drm/xe/xe_gt.c                    |  46 +++
 drivers/gpu/drm/xe/xe_guc_types.h             |   9 -
 drivers/gpu/drm/xe/xe_hw_engine.c             |  20 +
 drivers/gpu/drm/xe/xe_module.c                |   5 +
 drivers/gpu/drm/xe/xe_module.h                |   1 +
 drivers/gpu/drm/xe/xe_pci.c                   |   2 +-
 drivers/gpu/drm/xe/xe_uc.c                    |  21 +-
 drivers/gpu/drm/xe/xe_uc_fw.c                 | 257 +++++++++---
 drivers/gpu/drm/xe/xe_uc_fw.h                 |   3 +
 drivers/gpu/drm/xe/xe_uc_fw_abi.h             | 113 +++++
 drivers/gpu/drm/xe/xe_uc_fw_types.h           |  40 +-
 drivers/gpu/drm/xe/xe_uc_types.h              |   3 +
 drivers/gpu/drm/xe/xe_wa_oob.rules            |   1 +
 27 files changed, 1329 insertions(+), 89 deletions(-)
 create mode 100644 drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
 create mode 100644 drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h
 create mode 100644 drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
 create mode 100644 drivers/gpu/drm/xe/regs/xe_gsc_regs.h
 create mode 100644 drivers/gpu/drm/xe/xe_gsc.c
 create mode 100644 drivers/gpu/drm/xe/xe_gsc.h
 create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.c
 create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.h
 create mode 100644 drivers/gpu/drm/xe/xe_gsc_types.h

-- 
2.41.0


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

* [Intel-xe] [PATCH 01/12] drm/xe: implement driver initiated function-reset
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-11-07 23:46   ` John Harrison
  2023-10-27 22:29 ` [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware Daniele Ceraolo Spurio
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe; +Cc: Andrzej Hajda

From: Andrzej Hajda <andrzej.hajda@intel.com>

Driver initiated function-reset (FLR) is the highest level of reset
that we can trigger from within the driver. In contrast to PCI FLR it
doesn't require re-enumeration of PCI BAR. It can be useful in case
GT fails to reset. It is also the only way to trigger GSC reset from
the driver and can be used in future addition of GSC support.

v2:
  - use regs from xe_regs.h
  - move the flag to xe.mmio
  - call flr only on root gt
  - use BIOS protection check
  - copy/paste comments from i915
v3:
  - flr code moved to xe_device.c
v4:
  - needs_flr_on_fini moved to xe_device

Signed-off-by: Andrzej Hajda <andrzej.hajda@intel.com>
Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
---
 drivers/gpu/drm/xe/regs/xe_regs.h    |  7 +++
 drivers/gpu/drm/xe/xe_device.c       | 78 ++++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_device_types.h |  3 ++
 drivers/gpu/drm/xe/xe_gt.c           |  2 +
 4 files changed, 90 insertions(+)

diff --git a/drivers/gpu/drm/xe/regs/xe_regs.h b/drivers/gpu/drm/xe/regs/xe_regs.h
index 2240cd157603..a646d13af03a 100644
--- a/drivers/gpu/drm/xe/regs/xe_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_regs.h
@@ -57,8 +57,15 @@
 
 #define SOFTWARE_FLAGS_SPR33			XE_REG(0x4f084)
 
+#define GU_CNTL_PROTECTED			XE_REG(0x10100C)
+#define   DRIVERINT_FLR_DIS			REG_BIT(31)
+
 #define GU_CNTL					XE_REG(0x101010)
 #define   LMEM_INIT				REG_BIT(7)
+#define   DRIVERFLR				REG_BIT(31)
+
+#define GU_DEBUG				XE_REG(0x101018)
+#define   DRIVERFLR_STATUS			REG_BIT(31)
 
 #define XEHP_CLOCK_GATE_DIS			XE_REG(0x101014)
 #define   SGSI_SIDECLK_DIS			REG_BIT(17)
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 8341acf66e5f..515cdf599fab 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -5,6 +5,8 @@
 
 #include "xe_device.h"
 
+#include <linux/units.h>
+
 #include <drm/drm_aperture.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_gem_ttm_helper.h>
@@ -260,6 +262,78 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
 	return ERR_PTR(err);
 }
 
+/*
+ * The driver-initiated FLR is the highest level of reset that we can trigger
+ * from within the driver. It is different from the PCI FLR in that it doesn't
+ * fully reset the SGUnit and doesn't modify the PCI config space and therefore
+ * it doesn't require a re-enumeration of the PCI BARs. However, the
+ * driver-initiated FLR does still cause a reset of both GT and display and a
+ * memory wipe of local and stolen memory, so recovery would require a full HW
+ * re-init and saving/restoring (or re-populating) the wiped memory. Since we
+ * perform the FLR as the very last action before releasing access to the HW
+ * during the driver release flow, we don't attempt recovery at all, because
+ * if/when a new instance of i915 is bound to the device it will do a full
+ * re-init anyway.
+ */
+static void xe_driver_flr(struct xe_device *xe)
+{
+	const unsigned int flr_timeout = 3 * MICRO; /* specs recommend a 3s wait */
+	struct xe_gt *gt = xe_root_mmio_gt(xe);
+	int ret;
+
+	if (xe_mmio_read32(gt, GU_CNTL_PROTECTED) & DRIVERINT_FLR_DIS) {
+		drm_info_once(&xe->drm, "BIOS Disabled Driver-FLR\n");
+		return;
+	}
+
+	drm_dbg(&xe->drm, "Triggering Driver-FLR\n");
+
+	/*
+	 * Make sure any pending FLR requests have cleared by waiting for the
+	 * FLR trigger bit to go to zero. Also clear GU_DEBUG's DRIVERFLR_STATUS
+	 * to make sure it's not still set from a prior attempt (it's a write to
+	 * clear bit).
+	 * Note that we should never be in a situation where a previous attempt
+	 * is still pending (unless the HW is totally dead), but better to be
+	 * safe in case something unexpected happens
+	 */
+	ret = xe_mmio_wait32(gt, GU_CNTL, DRIVERFLR, 0, flr_timeout, NULL, false);
+	if (ret) {
+		drm_err(&xe->drm, "Driver-FLR-prepare wait for ready failed! %d\n", ret);
+		return;
+	}
+	xe_mmio_write32(gt, GU_DEBUG, DRIVERFLR_STATUS);
+
+	/* Trigger the actual Driver-FLR */
+	xe_mmio_rmw32(gt, GU_CNTL, 0, DRIVERFLR);
+
+	/* Wait for hardware teardown to complete */
+	ret = xe_mmio_wait32(gt, GU_CNTL, DRIVERFLR, 0, flr_timeout, NULL, false);
+	if (ret) {
+		drm_err(&xe->drm, "Driver-FLR-teardown wait completion failed! %d\n", ret);
+		return;
+	}
+
+	/* Wait for hardware/firmware re-init to complete */
+	ret = xe_mmio_wait32(gt, GU_DEBUG, DRIVERFLR_STATUS, DRIVERFLR_STATUS,
+			     flr_timeout, NULL, false);
+	if (ret) {
+		drm_err(&xe->drm, "Driver-FLR-reinit wait completion failed! %d\n", ret);
+		return;
+	}
+
+	/* Clear sticky completion status */
+	xe_mmio_write32(gt, GU_DEBUG, DRIVERFLR_STATUS);
+}
+
+static void xe_driver_flr_fini(struct drm_device *drm, void *arg)
+{
+	struct xe_device *xe = arg;
+
+	if (xe->needs_flr_on_fini)
+		xe_driver_flr(xe);
+}
+
 static void xe_device_sanitize(struct drm_device *drm, void *arg)
 {
 	struct xe_device *xe = arg;
@@ -294,6 +368,10 @@ int xe_device_probe(struct xe_device *xe)
 	if (err)
 		return err;
 
+	err = drmm_add_action_or_reset(&xe->drm, xe_driver_flr_fini, xe);
+	if (err)
+		return err;
+
 	for_each_gt(gt, xe, id) {
 		err = xe_pcode_probe(gt);
 		if (err)
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 44d622d4cc3a..9a0b0ccc1018 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -405,6 +405,9 @@ struct xe_device {
 	/** @heci_gsc: graphics security controller */
 	struct xe_heci_gsc heci_gsc;
 
+	/** @needs_flr_on_fini: requests function-reset on fini */
+	bool needs_flr_on_fini;
+
 	/* private: */
 
 #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index d380f67b3365..73c090762771 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -626,6 +626,8 @@ static int gt_reset(struct xe_gt *gt)
 	xe_uevent_gt_reset_failure(to_pci_dev(gt_to_xe(gt)->drm.dev),
 				   gt_to_tile(gt)->id, gt->info.id);
 
+	gt_to_xe(gt)->needs_flr_on_fini = true;
+
 	return err;
 }
 
-- 
2.41.0


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

* [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
  2023-10-27 22:29 ` [Intel-xe] [PATCH 01/12] drm/xe: implement driver initiated function-reset Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-10-31 14:09   ` Andrzej Hajda
  2023-11-07 23:07   ` John Harrison
  2023-10-27 22:29 ` [Intel-xe] [PATCH 03/12] drm/xe/uc: Rework uC version tracking Daniele Ceraolo Spurio
                   ` (13 subsequent siblings)
  15 siblings, 2 replies; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe

Major GuC versions greater than 70 will have the submission version in
the herader irrespective of their minor version number.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_uc_fw.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
index 3032c4f148d4..91d4a2272ee7 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.c
+++ b/drivers/gpu/drm/xe/xe_uc_fw.c
@@ -278,7 +278,7 @@ static void guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)
 	xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);
 	xe_gt_assert(gt, uc_fw->major_ver_found >= 70);
 
-	if (uc_fw->minor_ver_found >= 6) {
+	if (uc_fw->major_ver_found > 70 || uc_fw->minor_ver_found >= 6) {
 		/* v70.6.0 adds CSS header support */
 		guc->submission_state.version.major =
 			FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
-- 
2.41.0


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

* [Intel-xe] [PATCH 03/12] drm/xe/uc: Rework uC version tracking
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
  2023-10-27 22:29 ` [Intel-xe] [PATCH 01/12] drm/xe: implement driver initiated function-reset Daniele Ceraolo Spurio
  2023-10-27 22:29 ` [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-11-07 23:20   ` John Harrison
  2023-10-27 22:29 ` [Intel-xe] [PATCH 04/12] drm/xe/gsc: Introduce GSC FW Daniele Ceraolo Spurio
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe

The GSC firmware, support for which is coming soon for Xe, has both a
release version (updated on every release) and a compatibility version
(update only on interface changes). The GuC has something similar, with
a global release version and a submission version (which is also known
as the VF compatibility version). The main difference is that for the
GuC we still want to check the driver requirement against the release
version, while for the GSC we'll need to check against the compatibility
version.
Instead of special casing the GSC, this patch reworks the FW logic so
that we store both versions at the uc_fw level for all binaries and we
allow checking against either of the versions. Initially, we'll use it
to support GSC, but the logic could be re-used to allow VFs to check
against the GuC compatibility version.
Note that the GSC version has 4 numbers (major, minor, hotfix, build),
so support for that has been added as part of the rework and will be
used in follow-up patches.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
---
 drivers/gpu/drm/xe/xe_guc_types.h   |   9 --
 drivers/gpu/drm/xe/xe_uc_fw.c       | 141 +++++++++++++++++-----------
 drivers/gpu/drm/xe/xe_uc_fw_types.h |  35 +++++--
 3 files changed, 110 insertions(+), 75 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_guc_types.h b/drivers/gpu/drm/xe/xe_guc_types.h
index a5e58917a499..343cc39ce5bc 100644
--- a/drivers/gpu/drm/xe/xe_guc_types.h
+++ b/drivers/gpu/drm/xe/xe_guc_types.h
@@ -52,15 +52,6 @@ struct xe_guc {
 			/** @seqno: suspend fences seqno */
 			u32 seqno;
 		} suspend;
-		/** @version: submission version */
-		struct {
-			/** @major: major version of GuC submission */
-			u32 major;
-			/** @minor: minor version of GuC submission */
-			u32 minor;
-			/** @patch: patch version of GuC submission */
-			u32 patch;
-		} version;
 		/** @enabled: submission is enabled */
 		bool enabled;
 	} submission_state;
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
index 91d4a2272ee7..1f7dac394a1d 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.c
+++ b/drivers/gpu/drm/xe/xe_uc_fw.c
@@ -204,9 +204,12 @@ uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw)
 	for (i = 0; i < count && p <= entries[i].platform; i++) {
 		if (p == entries[i].platform) {
 			uc_fw->path = entries[i].path;
-			uc_fw->major_ver_wanted = entries[i].major;
-			uc_fw->minor_ver_wanted = entries[i].minor;
+			uc_fw->versions.wanted.major = entries[i].major;
+			uc_fw->versions.wanted.minor = entries[i].minor;
 			uc_fw->full_ver_required = entries[i].full_ver_required;
+
+			/* compatibility version checking coming soon */
+			uc_fw->versions.wanted_type = XE_UC_FW_VER_RELEASE;
 			break;
 		}
 	}
@@ -273,32 +276,30 @@ static void uc_fw_fini(struct drm_device *drm, void *arg)
 static void guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)
 {
 	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
-	struct xe_guc *guc = &gt->uc.guc;
+	struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
+	struct xe_uc_fw_version *compatibility = &uc_fw->versions.found[XE_UC_FW_VER_COMPATIBILITY];
 
 	xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);
-	xe_gt_assert(gt, uc_fw->major_ver_found >= 70);
+	xe_gt_assert(gt, release->major >= 70);
 
-	if (uc_fw->major_ver_found > 70 || uc_fw->minor_ver_found >= 6) {
+	if (release->major > 70 || release->minor >= 6) {
 		/* v70.6.0 adds CSS header support */
-		guc->submission_state.version.major =
-			FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
-				  css->submission_version);
-		guc->submission_state.version.minor =
-			FIELD_GET(CSS_SW_VERSION_UC_MINOR,
-				  css->submission_version);
-		guc->submission_state.version.patch =
-			FIELD_GET(CSS_SW_VERSION_UC_PATCH,
-				  css->submission_version);
-	} else if (uc_fw->minor_ver_found >= 3) {
+		compatibility->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
+						 css->submission_version);
+		compatibility->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR,
+						 css->submission_version);
+		compatibility->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH,
+						 css->submission_version);
+	} else if (release->minor >= 3) {
 		/* v70.3.0 introduced v1.1.0 */
-		guc->submission_state.version.major = 1;
-		guc->submission_state.version.minor = 1;
-		guc->submission_state.version.patch = 0;
+		compatibility->major = 1;
+		compatibility->minor = 1;
+		compatibility->patch = 0;
 	} else {
 		/* v70.0.0 introduced v1.0.0 */
-		guc->submission_state.version.major = 1;
-		guc->submission_state.version.minor = 0;
-		guc->submission_state.version.patch = 0;
+		compatibility->major = 1;
+		compatibility->minor = 0;
+		compatibility->patch = 0;
 	}
 
 	uc_fw->private_data_size = css->private_data_size;
@@ -307,30 +308,31 @@ static void guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)
 static int uc_fw_check_version_requirements(struct xe_uc_fw *uc_fw)
 {
 	struct xe_device *xe = uc_fw_to_xe(uc_fw);
+	struct xe_uc_fw_version *wanted = &uc_fw->versions.wanted;
+	struct xe_uc_fw_version *found = &uc_fw->versions.found[uc_fw->versions.wanted_type];
 
 	/* Driver has no requirement on any version, any is good. */
-	if (!uc_fw->major_ver_wanted)
+	if (!wanted->major)
 		return 0;
 
 	/*
 	 * If full version is required, both major and minor should match.
 	 * Otherwise, at least the major version.
 	 */
-	if (uc_fw->major_ver_wanted != uc_fw->major_ver_found ||
-	    (uc_fw->full_ver_required &&
-	     uc_fw->minor_ver_wanted != uc_fw->minor_ver_found)) {
+	if (wanted->major != found->major ||
+	    (uc_fw->full_ver_required && wanted->minor != found->minor)) {
 		drm_notice(&xe->drm, "%s firmware %s: unexpected version: %u.%u != %u.%u\n",
 			   xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
-			   uc_fw->major_ver_found, uc_fw->minor_ver_found,
-			   uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
+			   found->major, found->minor,
+			   wanted->major, wanted->minor);
 		goto fail;
 	}
 
-	if (uc_fw->minor_ver_wanted > uc_fw->minor_ver_found) {
+	if (wanted->minor > found->minor) {
 		drm_notice(&xe->drm, "%s firmware (%u.%u) is recommended, but only (%u.%u) was found in %s\n",
 			   xe_uc_fw_type_repr(uc_fw->type),
-			   uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted,
-			   uc_fw->major_ver_found, uc_fw->minor_ver_found,
+			   wanted->major, wanted->minor,
+			   found->major, found->minor,
 			   uc_fw->path);
 		drm_info(&xe->drm, "Consider updating your linux-firmware pkg or downloading from %s\n",
 			 XE_UC_FIRMWARE_URL);
@@ -349,6 +351,7 @@ static int uc_fw_check_version_requirements(struct xe_uc_fw *uc_fw)
 static int parse_css_header(struct xe_uc_fw *uc_fw, const void *fw_data, size_t fw_size)
 {
 	struct xe_device *xe = uc_fw_to_xe(uc_fw);
+	struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
 	struct uc_css_header *css;
 	size_t size;
 
@@ -390,12 +393,9 @@ static int parse_css_header(struct xe_uc_fw *uc_fw, const void *fw_data, size_t
 	}
 
 	/* Get version numbers from the CSS header */
-	uc_fw->major_ver_found = FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
-					   css->sw_version);
-	uc_fw->minor_ver_found = FIELD_GET(CSS_SW_VERSION_UC_MINOR,
-					   css->sw_version);
-	uc_fw->patch_ver_found = FIELD_GET(CSS_SW_VERSION_UC_PATCH,
-					   css->sw_version);
+	release->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR, css->sw_version);
+	release->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR, css->sw_version);
+	release->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH, css->sw_version);
 
 	if (uc_fw->type == XE_UC_FW_TYPE_GUC)
 		guc_read_css_info(uc_fw, css);
@@ -431,6 +431,7 @@ static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t siz
 	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
 	struct xe_device *xe = gt_to_xe(gt);
 	const struct gsc_cpd_header_v2 *header = data;
+	struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
 	const struct gsc_manifest_header *manifest;
 	size_t min_size = sizeof(*header);
 	u32 offset;
@@ -468,9 +469,9 @@ static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t siz
 
 	manifest = data + offset;
 
-	uc_fw->major_ver_found = manifest->fw_version.major;
-	uc_fw->minor_ver_found = manifest->fw_version.minor;
-	uc_fw->patch_ver_found = manifest->fw_version.hotfix;
+	release->major = manifest->fw_version.major;
+	release->minor = manifest->fw_version.minor;
+	release->patch = manifest->fw_version.hotfix;
 
 	/* then optionally look for the css header */
 	if (css_entry) {
@@ -524,12 +525,25 @@ static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)
 	return 0;
 }
 
+#define print_uc_fw_version(p_, version_, prefix_, ...) \
+do { \
+	struct xe_uc_fw_version *ver_ = (version_); \
+	if (ver_->build) \
+		drm_printf(p_, prefix_ " version %u.%u.%u.%u\n", ##__VA_ARGS__, \
+			   ver_->major, ver_->minor, \
+			   ver_->patch, ver_->build); \
+	else \
+		drm_printf(p_, prefix_ " version %u.%u.%u\n", ##__VA_ARGS__, \
+			  ver_->major, ver_->minor, ver_->patch); \
+} while(0);
+
 int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
 {
 	struct xe_device *xe = uc_fw_to_xe(uc_fw);
 	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
 	struct xe_tile *tile = gt_to_tile(gt);
 	struct device *dev = xe->drm.dev;
+	struct drm_printer p = drm_info_printer(dev);
 	const struct firmware *fw = NULL;
 	struct xe_bo *obj;
 	int err;
@@ -567,9 +581,10 @@ int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
 	if (err)
 		goto fail;
 
-	drm_info(&xe->drm, "Using %s firmware from %s version %u.%u.%u\n",
-		 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
-		 uc_fw->major_ver_found, uc_fw->minor_ver_found, uc_fw->patch_ver_found);
+	print_uc_fw_version(&p,
+			    &uc_fw->versions.found[XE_UC_FW_VER_RELEASE],
+			    "Using %s firmware from %s",
+			    xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
 
 	err = uc_fw_check_version_requirements(uc_fw);
 	if (err)
@@ -686,26 +701,40 @@ int xe_uc_fw_upload(struct xe_uc_fw *uc_fw, u32 offset, u32 dma_flags)
 	return err;
 }
 
+static const char *version_type_repr(enum xe_uc_fw_version_types type)
+{
+	switch (type) {
+	case XE_UC_FW_VER_RELEASE:
+		return "release";
+	case XE_UC_FW_VER_COMPATIBILITY:
+		return "compatibility";
+	default:
+		return "Unknown version type";
+	}
+}
 
 void xe_uc_fw_print(struct xe_uc_fw *uc_fw, struct drm_printer *p)
 {
+	int i;
+
 	drm_printf(p, "%s firmware: %s\n",
 		   xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
 	drm_printf(p, "\tstatus: %s\n",
 		   xe_uc_fw_status_repr(uc_fw->status));
-	drm_printf(p, "\tversion: wanted %u.%u, found %u.%u.%u\n",
-		   uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted,
-		   uc_fw->major_ver_found, uc_fw->minor_ver_found, uc_fw->patch_ver_found);
-	drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);
-	drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);
-
-	if (uc_fw->type == XE_UC_FW_TYPE_GUC) {
-		struct xe_gt *gt = uc_fw_to_gt(uc_fw);
-		struct xe_guc *guc = &gt->uc.guc;
-
-		drm_printf(p, "\tSubmit version: %u.%u.%u\n",
-			   guc->submission_state.version.major,
-			   guc->submission_state.version.minor,
-			   guc->submission_state.version.patch);
+
+	print_uc_fw_version(p, &uc_fw->versions.wanted, "\twanted %s",
+			    version_type_repr(uc_fw->versions.wanted_type));
+
+	for (i = 0; i < XE_UC_FW_VER_TYPE_COUNT; i++) {
+		struct xe_uc_fw_version *ver = &uc_fw->versions.found[i];
+
+		if (ver->major)
+			print_uc_fw_version(p, ver, "\tfound %s",
+					    version_type_repr(i));
 	}
+
+	if (uc_fw->ucode_size)
+		drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);
+	if (uc_fw->rsa_size)
+		drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);
 }
diff --git a/drivers/gpu/drm/xe/xe_uc_fw_types.h b/drivers/gpu/drm/xe/xe_uc_fw_types.h
index 1650599303c8..e4774c560e67 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw_types.h
+++ b/drivers/gpu/drm/xe/xe_uc_fw_types.h
@@ -59,6 +59,22 @@ enum xe_uc_fw_type {
 };
 #define XE_UC_FW_NUM_TYPES 2
 
+/**
+ * struct xe_uc_fw_version - Version for XE micro controller firmware
+ */
+struct xe_uc_fw_version {
+	u16 major;
+	u16 minor;
+	u16 patch;
+	u16 build;
+};
+
+enum xe_uc_fw_version_types {
+	XE_UC_FW_VER_RELEASE,
+	XE_UC_FW_VER_COMPATIBILITY,
+	XE_UC_FW_VER_TYPE_COUNT
+};
+
 /**
  * struct xe_uc_fw - XE micro controller firmware
  */
@@ -98,16 +114,15 @@ struct xe_uc_fw {
 	 * version required per platform.
 	 */
 
-	/** @major_ver_wanted: major firmware version wanted by platform */
-	u16 major_ver_wanted;
-	/** @minor_ver_wanted: minor firmware version wanted by platform */
-	u16 minor_ver_wanted;
-	/** @major_ver_found: major version found in firmware blob */
-	u16 major_ver_found;
-	/** @minor_ver_found: major version found in firmware blob */
-	u16 minor_ver_found;
-	/** @patch_ver_found: patch version found in firmware blob */
-	u16 patch_ver_found;
+	/** @versions: FW versions wanted and found */
+	struct {
+		/** @wanted: firmware version wanted by platform */
+		struct xe_uc_fw_version wanted;
+		/** @wanted_type: type of firmware version wanted (release vs compatibility) */
+		enum xe_uc_fw_version_types wanted_type;
+		/** @found: fw versions found in firmware blob */
+		struct xe_uc_fw_version found[XE_UC_FW_VER_TYPE_COUNT];
+	} versions;
 
 	/** @rsa_size: RSA size */
 	u32 rsa_size;
-- 
2.41.0


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

* [Intel-xe] [PATCH 04/12] drm/xe/gsc: Introduce GSC FW
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (2 preceding siblings ...)
  2023-10-27 22:29 ` [Intel-xe] [PATCH 03/12] drm/xe/uc: Rework uC version tracking Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-11-07 23:26   ` John Harrison
  2023-10-27 22:29 ` [Intel-xe] [PATCH 05/12] drm/xe/gsc: Parse GSC FW header Daniele Ceraolo Spurio
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe

Add the basic definitions and init function. Same as HuC, GSC is only
supported on the media GT on MTL and newer platforms.
Note that the GSC requires submission resources which can't be allocated
during init (because we don't have the hwconfig yet), so it can't be
marked as loadable at the end of the init function. The allocation of
those resources will come in the patch that makes use of them to load
the FW.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
---
 drivers/gpu/drm/xe/Makefile         |  1 +
 drivers/gpu/drm/xe/xe_gsc.c         | 50 +++++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_gsc.h         | 13 ++++++++
 drivers/gpu/drm/xe/xe_gsc_types.h   | 19 +++++++++++
 drivers/gpu/drm/xe/xe_uc.c          |  9 ++++--
 drivers/gpu/drm/xe/xe_uc_fw.c       | 21 ++++++++++--
 drivers/gpu/drm/xe/xe_uc_fw.h       |  2 ++
 drivers/gpu/drm/xe/xe_uc_fw_types.h |  5 +--
 drivers/gpu/drm/xe/xe_uc_types.h    |  3 ++
 9 files changed, 116 insertions(+), 7 deletions(-)
 create mode 100644 drivers/gpu/drm/xe/xe_gsc.c
 create mode 100644 drivers/gpu/drm/xe/xe_gsc.h
 create mode 100644 drivers/gpu/drm/xe/xe_gsc_types.h

diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index cee57681732d..474b6044d054 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -57,6 +57,7 @@ xe-y += xe_bb.o \
 	xe_exec_queue.o \
 	xe_force_wake.o \
 	xe_ggtt.o \
+	xe_gsc.o \
 	xe_gt.o \
 	xe_gt_clock.o \
 	xe_gt_debugfs.o \
diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
new file mode 100644
index 000000000000..3f709577d73b
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_gsc.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include "xe_gsc.h"
+
+#include "xe_device.h"
+#include "xe_gt.h"
+#include "xe_gt_printk.h"
+#include "xe_uc_fw.h"
+
+static struct xe_gt *
+gsc_to_gt(struct xe_gsc *gsc)
+{
+	return container_of(gsc, struct xe_gt, uc.gsc);
+}
+
+int xe_gsc_init(struct xe_gsc *gsc)
+{
+	struct xe_gt *gt = gsc_to_gt(gsc);
+	struct xe_tile *tile = gt_to_tile(gt);
+	int ret;
+
+	gsc->fw.type = XE_UC_FW_TYPE_GSC;
+
+	/* The GSC uC is only available on the media GT */
+	if (tile->media_gt && (gt != tile->media_gt)) {
+		xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_NOT_SUPPORTED);
+		return 0;
+	}
+
+	/*
+	 * GSC can be "not supported" where GuC is instead supported, so we
+	 * don't want to fail if xe_uc_fw_init() returns an error due to that.
+	 * To avoid this problem, check the FW status before the return code.
+	 */
+	ret = xe_uc_fw_init(&gsc->fw);
+	if (!xe_uc_fw_is_enabled(&gsc->fw))
+		return 0;
+	else if (ret)
+		goto out;
+
+	return 0;
+
+out:
+	xe_gt_err(gt, "GSC init failed with %d", ret);
+	return ret;
+}
+
diff --git a/drivers/gpu/drm/xe/xe_gsc.h b/drivers/gpu/drm/xe/xe_gsc.h
new file mode 100644
index 000000000000..baa7f21f4204
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_gsc.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _XE_GSC_H_
+#define _XE_GSC_H_
+
+#include "xe_gsc_types.h"
+
+int xe_gsc_init(struct xe_gsc *gsc);
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h b/drivers/gpu/drm/xe/xe_gsc_types.h
new file mode 100644
index 000000000000..135f156e3736
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_gsc_types.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _XE_GSC_TYPES_H_
+#define _XE_GSC_TYPES_H_
+
+#include "xe_uc_fw_types.h"
+
+/**
+ * struct xe_gsc - GSC
+ */
+struct xe_gsc {
+	/** @fw: Generic uC firmware management */
+	struct xe_uc_fw fw;
+};
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
index 784f53c5f282..b67154c78dff 100644
--- a/drivers/gpu/drm/xe/xe_uc.c
+++ b/drivers/gpu/drm/xe/xe_uc.c
@@ -6,6 +6,7 @@
 #include "xe_uc.h"
 
 #include "xe_device.h"
+#include "xe_gsc.h"
 #include "xe_gt.h"
 #include "xe_guc.h"
 #include "xe_guc_pc.h"
@@ -32,8 +33,8 @@ int xe_uc_init(struct xe_uc *uc)
 	int ret;
 
 	/*
-	 * We call the GuC/HuC init functions even if GuC submission is off to
-	 * correctly move our tracking of the FW state to "disabled".
+	 * We call the GuC/HuC/GSC init functions even if GuC submission is off
+	 * to correctly move our tracking of the FW state to "disabled".
 	 */
 
 	ret = xe_guc_init(&uc->guc);
@@ -44,6 +45,10 @@ int xe_uc_init(struct xe_uc *uc)
 	if (ret)
 		goto err;
 
+	ret = xe_gsc_init(&uc->gsc);
+	if (ret)
+		goto err;
+
 	if (!xe_device_uc_enabled(uc_to_xe(uc)))
 		return 0;
 
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
index 1f7dac394a1d..af3e5cba606f 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.c
+++ b/drivers/gpu/drm/xe/xe_uc_fw.c
@@ -158,11 +158,18 @@ XE_HUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
 static struct xe_gt *
 __uc_fw_to_gt(struct xe_uc_fw *uc_fw, enum xe_uc_fw_type type)
 {
-	if (type == XE_UC_FW_TYPE_GUC)
+	XE_WARN_ON(type >= XE_UC_FW_NUM_TYPES);
+
+	switch (type) {
+	case XE_UC_FW_TYPE_GUC:
 		return container_of(uc_fw, struct xe_gt, uc.guc.fw);
+	case XE_UC_FW_TYPE_HUC:
+		return container_of(uc_fw, struct xe_gt, uc.huc.fw);
+	case XE_UC_FW_TYPE_GSC:
+		return container_of(uc_fw, struct xe_gt, uc.gsc.fw);
+	}
 
-	XE_WARN_ON(type != XE_UC_FW_TYPE_HUC);
-	return container_of(uc_fw, struct xe_gt, uc.huc.fw);
+	return NULL;
 }
 
 static struct xe_gt *uc_fw_to_gt(struct xe_uc_fw *uc_fw)
@@ -197,6 +204,14 @@ uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw)
 	u32 count;
 	int i;
 
+	/*
+	 * GSC FW support is still not fully in place, so we're not defining
+	 * the FW blob yet because we don't want the driver to attempt to load
+	 * it until we're ready for it.
+	 */
+	if (uc_fw->type == XE_UC_FW_TYPE_GSC)
+		return;
+
 	xe_assert(xe, uc_fw->type < ARRAY_SIZE(blobs_all));
 	entries = blobs_all[uc_fw->type].entries;
 	count = blobs_all[uc_fw->type].count;
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.h b/drivers/gpu/drm/xe/xe_uc_fw.h
index 1d1a0c156cdf..d4682b0276e2 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.h
+++ b/drivers/gpu/drm/xe/xe_uc_fw.h
@@ -96,6 +96,8 @@ static inline const char *xe_uc_fw_type_repr(enum xe_uc_fw_type type)
 		return "GuC";
 	case XE_UC_FW_TYPE_HUC:
 		return "HuC";
+	case XE_UC_FW_TYPE_GSC:
+		return "GSC";
 	}
 	return "uC";
 }
diff --git a/drivers/gpu/drm/xe/xe_uc_fw_types.h b/drivers/gpu/drm/xe/xe_uc_fw_types.h
index e4774c560e67..239256bfdb07 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw_types.h
+++ b/drivers/gpu/drm/xe/xe_uc_fw_types.h
@@ -55,9 +55,10 @@ enum xe_uc_fw_status {
 
 enum xe_uc_fw_type {
 	XE_UC_FW_TYPE_GUC = 0,
-	XE_UC_FW_TYPE_HUC
+	XE_UC_FW_TYPE_HUC,
+	XE_UC_FW_TYPE_GSC
 };
-#define XE_UC_FW_NUM_TYPES 2
+#define XE_UC_FW_NUM_TYPES 3
 
 /**
  * struct xe_uc_fw_version - Version for XE micro controller firmware
diff --git a/drivers/gpu/drm/xe/xe_uc_types.h b/drivers/gpu/drm/xe/xe_uc_types.h
index 49bef6498b85..9924e4484866 100644
--- a/drivers/gpu/drm/xe/xe_uc_types.h
+++ b/drivers/gpu/drm/xe/xe_uc_types.h
@@ -6,6 +6,7 @@
 #ifndef _XE_UC_TYPES_H_
 #define _XE_UC_TYPES_H_
 
+#include "xe_gsc_types.h"
 #include "xe_guc_types.h"
 #include "xe_huc_types.h"
 #include "xe_wopcm_types.h"
@@ -18,6 +19,8 @@ struct xe_uc {
 	struct xe_guc guc;
 	/** @huc: HuC */
 	struct xe_huc huc;
+	/** @gsc: Graphics Security Controller */
+	struct xe_gsc gsc;
 	/** @wopcm: WOPCM */
 	struct xe_wopcm wopcm;
 };
-- 
2.41.0


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

* [Intel-xe] [PATCH 05/12] drm/xe/gsc: Parse GSC FW header
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (3 preceding siblings ...)
  2023-10-27 22:29 ` [Intel-xe] [PATCH 04/12] drm/xe/gsc: Introduce GSC FW Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-11-07 23:45   ` John Harrison
  2023-10-27 22:29 ` [Intel-xe] [PATCH 06/12] drm/xe/gsc: GSC FW load Daniele Ceraolo Spurio
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe; +Cc: Lucas De Marchi

The GSC blob starts with a layout header, from which we can move to the
boot directory, which in turns allows us to find the CPD. The CPD uses
the same format as the one in the HuC binary, so we can re-use the same
parsing code to get to the manifest, which contains the release and
security versions of the FW.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
---
 drivers/gpu/drm/xe/xe_gsc_types.h |   3 +
 drivers/gpu/drm/xe/xe_uc_fw.c     |  77 ++++++++++++++++++++
 drivers/gpu/drm/xe/xe_uc_fw_abi.h | 113 ++++++++++++++++++++++++++++++
 3 files changed, 193 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h b/drivers/gpu/drm/xe/xe_gsc_types.h
index 135f156e3736..1bc50583fe58 100644
--- a/drivers/gpu/drm/xe/xe_gsc_types.h
+++ b/drivers/gpu/drm/xe/xe_gsc_types.h
@@ -14,6 +14,9 @@
 struct xe_gsc {
 	/** @fw: Generic uC firmware management */
 	struct xe_uc_fw fw;
+
+	/** @security_version: SVN found in the fetched blob */
+	u32 security_version;
 };
 
 #endif
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
index af3e5cba606f..bb38a76eb4a6 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.c
+++ b/drivers/gpu/drm/xe/xe_uc_fw.c
@@ -12,6 +12,7 @@
 #include "xe_bo.h"
 #include "xe_device_types.h"
 #include "xe_force_wake.h"
+#include "xe_gsc.h"
 #include "xe_gt.h"
 #include "xe_map.h"
 #include "xe_mmio.h"
@@ -488,6 +489,13 @@ static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t siz
 	release->minor = manifest->fw_version.minor;
 	release->patch = manifest->fw_version.hotfix;
 
+	if (uc_fw->type == XE_UC_FW_TYPE_GSC) {
+		struct xe_gsc * gsc = container_of(uc_fw, struct xe_gsc, fw);
+
+		release->build = manifest->fw_version.build;
+		gsc->security_version = manifest->security_version;
+	}
+
 	/* then optionally look for the css header */
 	if (css_entry) {
 		int ret;
@@ -517,6 +525,73 @@ static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t siz
 	return 0;
 }
 
+static int parse_gsc_layout(struct xe_uc_fw *uc_fw, const void *data, size_t size)
+{
+	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
+	const struct gsc_layout_pointers *layout = data;
+	const struct gsc_bpdt_header *bpdt_header = NULL;
+	const struct gsc_bpdt_entry *bpdt_entry = NULL;
+	size_t min_size = sizeof(*layout);
+	int i;
+
+	if (size < min_size) {
+		xe_gt_err(gt, "GSC FW too small! %zu < %zu\n", size, min_size);
+		return -ENODATA;
+	}
+
+	min_size = layout->boot1.offset + layout->boot1.size;
+	if (size < min_size) {
+		xe_gt_err(gt, "GSC FW too small for boot section! %zu < %zu\n",
+			  size, min_size);
+		return -ENODATA;
+	}
+
+	min_size = sizeof(*bpdt_header);
+	if (layout->boot1.size < min_size) {
+		xe_gt_err(gt, "GSC FW boot section too small for BPDT header: %u < %zu\n",
+			  layout->boot1.size, min_size);
+		return -ENODATA;
+	}
+
+	bpdt_header = data + layout->boot1.offset;
+	if (bpdt_header->signature != GSC_BPDT_HEADER_SIGNATURE) {
+		xe_gt_err(gt, "invalid signature for BPDT header: 0x%08x!\n",
+			  bpdt_header->signature);
+		return -EINVAL;
+	}
+
+	min_size += sizeof(*bpdt_entry) * bpdt_header->descriptor_count;
+	if (layout->boot1.size < min_size) {
+		xe_gt_err(gt, "GSC FW boot section too small for BPDT entries: %u < %zu\n",
+			  layout->boot1.size, min_size);
+		return -ENODATA;
+	}
+
+	bpdt_entry = (void *)bpdt_header + sizeof(*bpdt_header);
+	for (i = 0; i < bpdt_header->descriptor_count; i++, bpdt_entry++) {
+		if ((bpdt_entry->type & GSC_BPDT_ENTRY_TYPE_MASK) !=
+		    GSC_BPDT_ENTRY_TYPE_GSC_RBE)
+			continue;
+
+		min_size = bpdt_entry->sub_partition_offset;
+
+		/* the CPD header parser will check that the CPD header fits */
+		if (layout->boot1.size < min_size) {
+			xe_gt_err(gt, "GSC FW boot section too small for CPD offset: %u < %zu\n",
+				  layout->boot1.size, min_size);
+			return -ENODATA;
+		}
+
+		return parse_cpd_header(uc_fw,
+					(void *)bpdt_header + min_size,
+					layout->boot1.size - min_size,
+					"RBEP.man", NULL);
+	}
+
+	xe_gt_err(gt, "couldn't find CPD header in GSC binary!\n");
+	return -ENODATA;
+}
+
 static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)
 {
 	int ret;
@@ -526,6 +601,8 @@ static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)
 	 * releases use GSC CPD headers.
 	 */
 	switch (uc_fw->type) {
+	case XE_UC_FW_TYPE_GSC:
+		return parse_gsc_layout(uc_fw, fw->data, fw->size);
 	case XE_UC_FW_TYPE_HUC:
 		ret = parse_cpd_header(uc_fw, fw->data, fw->size, "HUCP.man", "huc_fw");
 		if (!ret || ret != -ENOENT)
diff --git a/drivers/gpu/drm/xe/xe_uc_fw_abi.h b/drivers/gpu/drm/xe/xe_uc_fw_abi.h
index d6725c963251..edf2a448f4bb 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw_abi.h
+++ b/drivers/gpu/drm/xe/xe_uc_fw_abi.h
@@ -140,6 +140,58 @@ static_assert(sizeof(struct uc_css_header) == 128);
  *	|      RSA Key (MTL+ only)                       |
  *	|      ...                                       |
  *	+================================================+
+ *
+ * The GSC binary starts instead with a layout header, which contains the
+ * locations of the various partitions of the binary. The one we're interested
+ * in is the boot1 partition, where we can find a BPDT header followed by
+ * entries, one of which points to the RBE sub-section of the partition, which
+ * contains the CPD. The GSC blob does not contain a CSS-based binary, so we
+ * only need to look for the manifest, which is under the "RBEP.man" CPD entry.
+ * Note that we have no need to find where the actual FW code is inside the
+ * image because the GSC ROM will itself parse the headers to find it and load
+ * it.
+ * The GSC firmware header layout looks like this::
+ *
+ *	+================================================+
+ *	|  Layout Pointers                               |
+ *	|      ...                                       |
+ *	|      Boot1 offset  >---------------------------|------o
+ *	|      ...                                       |      |
+ *	+================================================+      |
+ *	                                                        |
+ *	+================================================+      |
+ *	|  BPDT header                                   |<-----o
+ *	+================================================+
+ *	|  BPDT entries[]                                |
+ *	|      entry1                                    |
+ *	|      ...                                       |
+ *	|      entryX                                    |
+ *	|          type == GSC_RBE                       |
+ *	|          offset  >-----------------------------|------o
+ *	|      ...                                       |      |
+ *	+================================================+      |
+ *	                                                        |
+ *	+================================================+      |
+ *	|  CPD Header                                    |<-----o
+ *	+================================================+
+ *	|  CPD entries[]                                 |
+ *	|      entry1                                    |
+ *	|      ...                                       |
+ *	|      entryX                                    |
+ *	|          "RBEP.man"                            |
+ *	|           ...                                  |
+ *	|           offset  >----------------------------|------o
+ *	|      ...                                       |      |
+ *	+================================================+      |
+ *	                                                        |
+ *	+================================================+      |
+ *	| Manifest Header                                |<-----o
+ *	|  ...                                           |
+ *	|  FW version                                    |
+ *	|  ...                                           |
+ *	|  Security version                              |
+ *	|  ...                                           |
+ *	+================================================+
  */
 
 struct gsc_version {
@@ -149,6 +201,67 @@ struct gsc_version {
 	u16 build;
 } __packed;
 
+struct gsc_partition {
+	u32 offset;
+	u32 size;
+} __packed;
+
+struct gsc_layout_pointers {
+	u8 rom_bypass_vector[16];
+
+	/* size of pointers layout not including ROM bypass vector */
+	u16 size;
+
+	/*
+	 * bit0: Backup copy of layout pointers exist
+	 * bits1-15: reserved
+	 */
+	u8 flags;
+
+	u8 reserved;
+
+	u32 crc32;
+
+	struct gsc_partition datap;
+	struct gsc_partition boot1;
+	struct gsc_partition boot2;
+	struct gsc_partition boot3;
+	struct gsc_partition boot4;
+	struct gsc_partition boot5;
+	struct gsc_partition temp_pages;
+} __packed;
+
+/* Boot partition structures */
+struct gsc_bpdt_header {
+	u32 signature;
+#define GSC_BPDT_HEADER_SIGNATURE 0x000055AA
+
+	u16 descriptor_count; /* num of entries after the header */
+
+	u8 version;
+	u8 configuration;
+
+	u32 crc32;
+
+	u32 build_version;
+	struct gsc_version tool_version;
+} __packed;
+
+struct gsc_bpdt_entry {
+	/*
+	 * Bits 0-15: BPDT entry type
+	 * Bits 16-17: reserved
+	 * Bit 18: code sub-partition
+	 * Bits 19-31: reserved
+	 */
+	u32 type;
+#define GSC_BPDT_ENTRY_TYPE_MASK GENMASK(15, 0)
+#define GSC_BPDT_ENTRY_TYPE_GSC_RBE 0x1
+
+	u32 sub_partition_offset; /* from the base of the BPDT header */
+	u32 sub_partition_size;
+} __packed;
+
 /* Code partition directory (CPD) structures */
 struct gsc_cpd_header_v2 {
 	u32 header_marker;
-- 
2.41.0


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

* [Intel-xe] [PATCH 06/12] drm/xe/gsc: GSC FW load
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (4 preceding siblings ...)
  2023-10-27 22:29 ` [Intel-xe] [PATCH 05/12] drm/xe/gsc: Parse GSC FW header Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-11-08 22:17   ` John Harrison
  2023-10-27 22:29 ` [Intel-xe] [PATCH 07/12] drm/xe/gsc: Implement WA 14015076503 Daniele Ceraolo Spurio
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe

The GSC FW must be copied in a 4MB stolen memory allocation, whose GGTT
address is then passed as a parameter to a dedicated load instruction
submitted via the GSC engine.

Since the GSC load is relatively slow (up to 250ms), we perform it
asynchronously via a worker. This requires us to make sure that the
worker has stopped before suspending/unloading.

Note that we can't yet use xe_migrate_copy for the copy because it
doesn't work with stolen memory right now, so we do a memcpy from the
CPU side instead.

Bspec: 65306, 65346
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
---
 .../gpu/drm/xe/instructions/xe_gsc_commands.h |  34 +++
 .../gpu/drm/xe/instructions/xe_instr_defs.h   |   1 +
 drivers/gpu/drm/xe/regs/xe_gsc_regs.h         |  29 +++
 drivers/gpu/drm/xe/xe_gsc.c                   | 240 ++++++++++++++++++
 drivers/gpu/drm/xe/xe_gsc.h                   |   3 +
 drivers/gpu/drm/xe/xe_gsc_types.h             |  17 ++
 drivers/gpu/drm/xe/xe_uc.c                    |  12 +-
 7 files changed, 335 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
 create mode 100644 drivers/gpu/drm/xe/regs/xe_gsc_regs.h

diff --git a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
new file mode 100644
index 000000000000..c7a833d7f965
--- /dev/null
+++ b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _XE_GSC_COMMANDS_H_
+#define _XE_GSC_COMMANDS_H_
+
+#include "instructions/xe_instr_defs.h"
+
+/*
+ * All GSCCS-specific commands have fixed length, so we can include it in the
+ * defines. Note that the generic GSC command header structure includes an
+ * optional data field in bits 9-21, but there are no commands that actually use
+ * it; some of the commands are instead defined as having an extended length
+ * field spanning bits 0-15, even if the extra bits are not required because the
+ * longest GSCCS command is only 8 dwords. To handle this, the defines below use
+ * a single field for both data and len. If we ever get a commands that does
+ * actually have data and this approach doesn't work for it we can re-work it
+ * at that point.
+ */
+
+#define GSC_OPCODE		REG_GENMASK(28, 22)
+#define GSC_CMD_DATA_AND_LEN	REG_GENMASK(21, 0)
+
+#define __GSC_INSTR(op, dl) \
+	(XE_INSTR_GSC | \
+	REG_FIELD_PREP(GSC_OPCODE, op) | \
+	REG_FIELD_PREP(GSC_CMD_DATA_AND_LEN, dl))
+
+#define GSC_FW_LOAD __GSC_INSTR(1, 2)
+#define   GSC_FW_LOAD_LIMIT_VALID REG_BIT(31)
+
+#endif
diff --git a/drivers/gpu/drm/xe/instructions/xe_instr_defs.h b/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
index e403b4fcc20a..04179b2a48e1 100644
--- a/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
+++ b/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
@@ -15,6 +15,7 @@
  */
 #define XE_INSTR_CMD_TYPE		GENMASK(31, 29)
 #define   XE_INSTR_MI			REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x0)
+#define   XE_INSTR_GSC			REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x2)
 #define   XE_INSTR_GFXPIPE		REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x3)
 
 /*
diff --git a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
new file mode 100644
index 000000000000..22d2ad9cb64d
--- /dev/null
+++ b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _XE_GSC_REGS_H_
+#define _XE_GSC_REGS_H_
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#include "regs/xe_reg_defs.h"
+
+/* Definitions of GSC H/W registers, bits, etc */
+
+#define MTL_GSC_HECI1_BASE	0x00116000
+#define MTL_GSC_HECI2_BASE	0x00117000
+
+/*
+ * The FWSTS register values are FW defined and can be different between
+ * HECI1 and HECI2
+ */
+#define HECI_FWSTS1(base)				XE_REG((base) + 0xc40)
+#define   HECI1_FWSTS1_CURRENT_STATE			REG_GENMASK(3, 0)
+#define   HECI1_FWSTS1_CURRENT_STATE_RESET		0
+#define   HECI1_FWSTS1_PROXY_STATE_NORMAL		5
+#define   HECI1_FWSTS1_INIT_COMPLETE			REG_BIT(9)
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
index 3f709577d73b..7e5ba9039163 100644
--- a/drivers/gpu/drm/xe/xe_gsc.c
+++ b/drivers/gpu/drm/xe/xe_gsc.c
@@ -5,10 +5,20 @@
 
 #include "xe_gsc.h"
 
+#include <drm/drm_managed.h>
+
+#include "xe_bb.h"
+#include "xe_bo.h"
 #include "xe_device.h"
+#include "xe_exec_queue.h"
 #include "xe_gt.h"
 #include "xe_gt_printk.h"
+#include "xe_map.h"
+#include "xe_mmio.h"
+#include "xe_sched_job.h"
 #include "xe_uc_fw.h"
+#include "instructions/xe_gsc_commands.h"
+#include "regs/xe_gsc_regs.h"
 
 static struct xe_gt *
 gsc_to_gt(struct xe_gsc *gsc)
@@ -16,6 +26,134 @@ gsc_to_gt(struct xe_gsc *gsc)
 	return container_of(gsc, struct xe_gt, uc.gsc);
 }
 
+static int memcpy_fw(struct xe_gsc *gsc)
+{
+	struct xe_gt *gt = gsc_to_gt(gsc);
+	struct xe_device *xe = gt_to_xe(gt);
+	u32 fw_size = gsc->fw.size;
+	void *storage;
+
+	/*
+	 * FIXME: xe_migrate_copy does not work with stolen mem yet, so we use
+	 * a memcpy for now.
+	 */
+	storage = kmalloc(fw_size, GFP_KERNEL);
+	if (!storage)
+		return -ENOMEM;
+
+	xe_map_memcpy_from(xe, storage, &gsc->fw.bo->vmap, 0, fw_size);
+	xe_map_memcpy_to(xe, &gsc->private->vmap, 0, storage, fw_size);
+	xe_map_memset(xe, &gsc->private->vmap, fw_size, 0, gsc->private->size - fw_size);
+
+	kfree(storage);
+
+	return 0;
+}
+
+static int emit_gsc_upload(struct xe_gsc *gsc)
+{
+	struct xe_gt *gt = gsc_to_gt(gsc);
+	u32 offset = xe_bo_ggtt_addr(gsc->private);
+	struct xe_bb *bb;
+	struct xe_sched_job *job;
+	struct dma_fence *fence;
+	long timeout;
+
+	bb = xe_bb_new(gt, 4, false);
+	if (IS_ERR(bb))
+		return PTR_ERR(bb);
+
+	bb->cs[bb->len++] = GSC_FW_LOAD;
+	bb->cs[bb->len++] = lower_32_bits(offset);
+	bb->cs[bb->len++] = upper_32_bits(offset);
+	bb->cs[bb->len++] = (gsc->private->size / SZ_4K) | GSC_FW_LOAD_LIMIT_VALID;
+
+	job = xe_bb_create_job(gsc->q, bb);
+	if (IS_ERR(job)) {
+		xe_bb_free(bb, NULL);
+		return PTR_ERR(job);
+	}
+
+	xe_sched_job_arm(job);
+	fence = dma_fence_get(&job->drm.s_fence->finished);
+	xe_sched_job_push(job);
+
+	timeout = dma_fence_wait_timeout(fence, false, HZ);
+	dma_fence_put(fence);
+	xe_bb_free(bb, NULL);
+	if (timeout < 0)
+		return timeout;
+	else if (!timeout)
+		return -ETIME;
+
+	return 0;
+}
+
+static int gsc_fw_is_loaded(struct xe_gt *gt)
+{
+	return xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)) &
+			      HECI1_FWSTS1_INIT_COMPLETE;
+}
+
+static int gsc_fw_wait(struct xe_gt *gt)
+{
+	return xe_mmio_wait32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE),
+			      HECI1_FWSTS1_INIT_COMPLETE,
+			      HECI1_FWSTS1_INIT_COMPLETE,
+			      500, NULL, false);
+}
+
+static int gsc_upload(struct xe_gsc *gsc)
+{
+	struct xe_gt *gt = gsc_to_gt(gsc);
+	int err;
+
+	if (XE_WARN_ON(!xe_uc_fw_is_loadable(&gsc->fw) || !gsc->q || gsc_fw_is_loaded(gt)))
+		return 0;
+
+	err = memcpy_fw(gsc);
+	if (err) {
+		xe_gt_err(gt, "Failed to memcpy GSC FW\n");
+		return err;
+	}
+
+	err = emit_gsc_upload(gsc);
+	if (err) {
+		xe_gt_err(gt, "Failed to emit GSC FW upload (%pe)\n", ERR_PTR(err));
+		return err;
+	}
+
+	err = gsc_fw_wait(gt);
+	if (err) {
+		xe_gt_err(gt, "Failed to wait for GSC load (%pe)\n", ERR_PTR(err));
+		return err;
+	}
+
+	xe_gt_dbg(gt, "GSC FW async load completed\n");
+
+	return 0;
+}
+
+static void gsc_work(struct work_struct *work)
+{
+	struct xe_gsc *gsc = container_of(work, typeof(*gsc), work);
+	struct xe_gt *gt = gsc_to_gt(gsc);
+	struct xe_device *xe = gt_to_xe(gt);
+	int ret;
+
+	xe_device_mem_access_get(xe);
+	xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC);
+
+	ret = gsc_upload(gsc);
+	if (ret)
+		xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_LOAD_FAIL);
+	else
+		xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
+
+	xe_force_wake_put(gt_to_fw(gt), XE_FW_GSC);
+	xe_device_mem_access_put(xe);
+}
+
 int xe_gsc_init(struct xe_gsc *gsc)
 {
 	struct xe_gt *gt = gsc_to_gt(gsc);
@@ -23,6 +161,7 @@ int xe_gsc_init(struct xe_gsc *gsc)
 	int ret;
 
 	gsc->fw.type = XE_UC_FW_TYPE_GSC;
+	INIT_WORK(&gsc->work, gsc_work);
 
 	/* The GSC uC is only available on the media GT */
 	if (tile->media_gt && (gt != tile->media_gt)) {
@@ -48,3 +187,104 @@ int xe_gsc_init(struct xe_gsc *gsc)
 	return ret;
 }
 
+static void free_resources(struct drm_device *drm, void *arg)
+{
+	struct xe_gsc *gsc = arg;
+
+	if (gsc->wq) {
+		destroy_workqueue(gsc->wq);
+		gsc->wq = NULL;
+	}
+
+	if (gsc->q) {
+		xe_exec_queue_put(gsc->q);
+		gsc->q = NULL;
+	}
+
+	if (gsc->private) {
+		xe_bo_unpin_map_no_vm(gsc->private);
+		gsc->private = NULL;
+	}
+}
+
+int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc)
+{
+	struct xe_gt *gt = gsc_to_gt(gsc);
+	struct xe_tile *tile = gt_to_tile(gt);
+	struct xe_device *xe = gt_to_xe(gt);
+	struct xe_hw_engine *hwe = xe_gt_hw_engine(gt, XE_ENGINE_CLASS_OTHER, 0, true);
+	struct xe_exec_queue *q;
+	struct workqueue_struct *wq;
+	struct xe_bo *bo;
+	int err;
+
+	if (!xe_uc_fw_is_available(&gsc->fw))
+		return 0;
+
+	if (!hwe)
+		return -ENODEV;
+
+	bo = xe_bo_create_pin_map(xe, tile, NULL, SZ_4M,
+				  ttm_bo_type_kernel,
+				  XE_BO_CREATE_STOLEN_BIT |
+				  XE_BO_CREATE_GGTT_BIT);
+	if (IS_ERR(bo))
+		return PTR_ERR(bo);
+
+	q = xe_exec_queue_create(xe, NULL,
+				 BIT(hwe->logical_instance), 1, hwe,
+				 EXEC_QUEUE_FLAG_KERNEL |
+				 EXEC_QUEUE_FLAG_PERMANENT);
+	if (IS_ERR(q)) {
+		xe_gt_err(gt, "Failed to create queue for GSC submission\n");
+		err = PTR_ERR(q);
+		goto out_bo;
+	}
+
+	wq = alloc_ordered_workqueue("gsc-ordered-wq", 0);
+	if (!wq) {
+		err = -ENOMEM;
+		goto out_q;
+	}
+
+	gsc->private = bo;
+	gsc->q = q;
+	gsc->wq = wq;
+
+	err = drmm_add_action_or_reset(&xe->drm, free_resources, gsc);
+	if (err)
+		return err;
+
+	xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_LOADABLE);
+
+	return 0;
+
+out_q:
+	xe_exec_queue_put(q);
+out_bo:
+	xe_bo_unpin_map_no_vm(bo);
+	return err;
+
+}
+
+void xe_gsc_load_start(struct xe_gsc *gsc)
+{
+	struct xe_gt *gt = gsc_to_gt(gsc);
+
+	if (!xe_uc_fw_is_loadable(&gsc->fw) || !gsc->q)
+		return;
+
+	/* GSC FW survives GT reset and D3Hot */
+	if (gsc_fw_is_loaded(gt)) {
+		xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
+		return;
+	}
+
+	queue_work(gsc->wq, &gsc->work);
+}
+
+void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc)
+{
+	if (xe_uc_fw_is_loadable(&gsc->fw) && gsc->wq)
+		flush_work(&gsc->work);
+}
diff --git a/drivers/gpu/drm/xe/xe_gsc.h b/drivers/gpu/drm/xe/xe_gsc.h
index baa7f21f4204..f870eddc77d4 100644
--- a/drivers/gpu/drm/xe/xe_gsc.h
+++ b/drivers/gpu/drm/xe/xe_gsc.h
@@ -9,5 +9,8 @@
 #include "xe_gsc_types.h"
 
 int xe_gsc_init(struct xe_gsc *gsc);
+int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc);
+void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc);
+void xe_gsc_load_start(struct xe_gsc *gsc);
 
 #endif
diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h b/drivers/gpu/drm/xe/xe_gsc_types.h
index 1bc50583fe58..57fefd66a7ea 100644
--- a/drivers/gpu/drm/xe/xe_gsc_types.h
+++ b/drivers/gpu/drm/xe/xe_gsc_types.h
@@ -6,8 +6,13 @@
 #ifndef _XE_GSC_TYPES_H_
 #define _XE_GSC_TYPES_H_
 
+#include <linux/workqueue.h>
+
 #include "xe_uc_fw_types.h"
 
+struct xe_bo;
+struct xe_exec_queue;
+
 /**
  * struct xe_gsc - GSC
  */
@@ -17,6 +22,18 @@ struct xe_gsc {
 
 	/** @security_version: SVN found in the fetched blob */
 	u32 security_version;
+
+	/** @private: Private data for use by the GSC FW */
+	struct xe_bo *private;
+
+	/** @q: Default queue used for submissions to GSC FW */
+	struct xe_exec_queue *q;
+
+	/** @wq: workqueue to handle jobs for delayed load and proxy handling */
+	struct workqueue_struct *wq;
+
+	/** @work: delayed load and proxy handling work */
+	struct work_struct work;
 };
 
 #endif
diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
index b67154c78dff..15dcd1f91e9c 100644
--- a/drivers/gpu/drm/xe/xe_uc.c
+++ b/drivers/gpu/drm/xe/xe_uc.c
@@ -74,11 +74,17 @@ int xe_uc_init(struct xe_uc *uc)
  */
 int xe_uc_init_post_hwconfig(struct xe_uc *uc)
 {
+	int err;
+
 	/* GuC submission not enabled, nothing to do */
 	if (!xe_device_uc_enabled(uc_to_xe(uc)))
 		return 0;
 
-	return xe_guc_init_post_hwconfig(&uc->guc);
+	err = xe_guc_init_post_hwconfig(&uc->guc);
+	if (err)
+		return err;
+
+	return xe_gsc_init_post_hwconfig(&uc->gsc);
 }
 
 static int uc_reset(struct xe_uc *uc)
@@ -173,6 +179,9 @@ int xe_uc_init_hw(struct xe_uc *uc)
 	ret = xe_huc_auth(&uc->huc);
 	xe_gt_assert(uc_to_gt(uc), !ret);
 
+	/* GSC load is async */
+	xe_gsc_load_start(&uc->gsc);
+
 	return 0;
 }
 
@@ -197,6 +206,7 @@ void xe_uc_gucrc_disable(struct xe_uc *uc)
 
 void xe_uc_stop_prepare(struct xe_uc *uc)
 {
+	xe_gsc_wait_for_worker_completion(&uc->gsc);
 	xe_guc_stop_prepare(&uc->guc);
 }
 
-- 
2.41.0


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

* [Intel-xe] [PATCH 07/12] drm/xe/gsc: Implement WA 14015076503
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (5 preceding siblings ...)
  2023-10-27 22:29 ` [Intel-xe] [PATCH 06/12] drm/xe/gsc: GSC FW load Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-11-08 22:22   ` John Harrison
  2023-10-27 22:29 ` [Intel-xe] [PATCH 08/12] drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload Daniele Ceraolo Spurio
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe

When the GSC FW is loaded, we need to inform it when a GSCCS reset is
coming and then wait 200ms for it to get ready to process the reset.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: John Harrison <john.c.harrison@intel.com>
---
 drivers/gpu/drm/xe/Makefile           |  2 +-
 drivers/gpu/drm/xe/regs/xe_gsc_regs.h | 10 ++++++
 drivers/gpu/drm/xe/xe_gt.c            | 44 +++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_wa_oob.rules    |  1 +
 4 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 474b6044d054..4a442dcf4d79 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -37,7 +37,7 @@ quiet_cmd_wa_oob = GEN     $(notdir $(generated_oob))
 $(generated_oob) &: $(obj)/xe_gen_wa_oob $(srctree)/$(src)/xe_wa_oob.rules
 	$(call cmd,wa_oob)
 
-$(obj)/xe_guc.o $(obj)/xe_migrate.o $(obj)/xe_ring_ops.o $(obj)/xe_vm.o $(obj)/xe_wa.o: $(generated_oob)
+$(obj)/xe_gt.o $(obj)/xe_guc.o $(obj)/xe_migrate.o $(obj)/xe_ring_ops.o $(obj)/xe_vm.o $(obj)/xe_wa.o: $(generated_oob)
 
 # Please keep these build lists sorted!
 
diff --git a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
index 22d2ad9cb64d..9a84b55d66ee 100644
--- a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
@@ -16,6 +16,13 @@
 #define MTL_GSC_HECI1_BASE	0x00116000
 #define MTL_GSC_HECI2_BASE	0x00117000
 
+#define HECI_H_CSR(base)	XE_REG((base) + 0x4)
+#define   HECI_H_CSR_IE		REG_BIT(0)
+#define   HECI_H_CSR_IS		REG_BIT(1)
+#define   HECI_H_CSR_IG		REG_BIT(2)
+#define   HECI_H_CSR_RDY	REG_BIT(3)
+#define   HECI_H_CSR_RST	REG_BIT(4)
+
 /*
  * The FWSTS register values are FW defined and can be different between
  * HECI1 and HECI2
@@ -26,4 +33,7 @@
 #define   HECI1_FWSTS1_PROXY_STATE_NORMAL		5
 #define   HECI1_FWSTS1_INIT_COMPLETE			REG_BIT(9)
 
+#define HECI_H_GS1(base)	XE_REG((base) + 0xc4c)
+#define   HECI_H_GS1_ER_PREP	REG_BIT(0)
+
 #endif
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index 73c090762771..0e8e24bded1c 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -10,8 +10,10 @@
 #include <drm/drm_managed.h>
 #include <drm/xe_drm.h>
 
+#include "generated/xe_wa_oob.h"
 #include "instructions/xe_gfxpipe_commands.h"
 #include "instructions/xe_mi_commands.h"
+#include "regs/xe_gsc_regs.h"
 #include "regs/xe_gt_regs.h"
 #include "xe_assert.h"
 #include "xe_bb.h"
@@ -504,16 +506,58 @@ int xe_gt_init(struct xe_gt *gt)
 	return 0;
 }
 
+static int gsc_fw_is_loaded(struct xe_gt *gt)
+{
+	return xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)) &
+			      HECI1_FWSTS1_INIT_COMPLETE;
+}
+
+static void wa_14015076503_start(struct xe_gt *gt)
+{
+	/* WA only applies if the GSC is loaded */
+	if (!XE_WA(gt, 14015076503) || !gsc_fw_is_loaded(gt))
+		return;
+
+	/*
+	 * wa_14015076503: if the GSC FW is loaded, we need to alert it that
+	 * we're going to do a GSC engine reset and then wait for 200ms for the
+	 * FW to get ready for it.
+	 */
+	xe_mmio_rmw32(gt, HECI_H_GS1(MTL_GSC_HECI2_BASE),
+		      0, HECI_H_GS1_ER_PREP);
+
+	/* make sure the reset bit is clear when writing the CSR reg */
+	xe_mmio_rmw32(gt, HECI_H_CSR(MTL_GSC_HECI2_BASE),
+		      HECI_H_CSR_RST, HECI_H_CSR_IG);
+	msleep(200);
+
+	return;
+}
+
+static void
+wa_14015076503_end(struct xe_gt *gt)
+{
+	if (!XE_WA(gt, 14015076503))
+		return;
+
+	xe_mmio_rmw32(gt, HECI_H_GS1(MTL_GSC_HECI2_BASE),
+		      HECI_H_GS1_ER_PREP, 0);
+}
+
 static int do_gt_reset(struct xe_gt *gt)
 {
 	int err;
 
+	wa_14015076503_start(gt);
+
 	xe_mmio_write32(gt, GDRST, GRDOM_FULL);
 	err = xe_mmio_wait32(gt, GDRST, GRDOM_FULL, 0, 5000, NULL, false);
 	if (err)
 		xe_gt_err(gt, "failed to clear GEN11_GRDOM_FULL (%pe)\n",
 			  ERR_PTR(err));
 
+	wa_14015076503_end(gt);
+
 	return err;
 }
 
diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules
index f3ff774dc4aa..132c35497f74 100644
--- a/drivers/gpu/drm/xe/xe_wa_oob.rules
+++ b/drivers/gpu/drm/xe/xe_wa_oob.rules
@@ -19,3 +19,4 @@
 		SUBPLATFORM(DG2, G12)
 16017236439	PLATFORM(PVC)
 22010954014	PLATFORM(DG2)
+14015076503	MEDIA_VERSION(1300)
-- 
2.41.0


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

* [Intel-xe] [PATCH 08/12] drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (6 preceding siblings ...)
  2023-10-27 22:29 ` [Intel-xe] [PATCH 07/12] drm/xe/gsc: Implement WA 14015076503 Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-11-08 22:24   ` John Harrison
  2023-10-27 22:29 ` [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions Daniele Ceraolo Spurio
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe

GSC is only killed by an FLR, so we need to trigger one on unload to
make sure we stop it. This is because we assign a chunk of memory to
the GSC as part of the FW load, so we need to make sure it stops
using it when we release it to the system on driver unload. Note that
this is not a problem of the unload per-se, because the GSC will not
touch that memory unless there are requests for it coming from the
driver; therefore, no accesses will happen while Xe is not loaded,
but if we re-load the driver then the GSC might wake up and try to
access that old memory location again.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 drivers/gpu/drm/xe/xe_gsc.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
index 7e5ba9039163..edf74780322a 100644
--- a/drivers/gpu/drm/xe/xe_gsc.c
+++ b/drivers/gpu/drm/xe/xe_gsc.c
@@ -106,6 +106,7 @@ static int gsc_fw_wait(struct xe_gt *gt)
 static int gsc_upload(struct xe_gsc *gsc)
 {
 	struct xe_gt *gt = gsc_to_gt(gsc);
+	struct xe_device *xe = gt_to_xe(gt);
 	int err;
 
 	if (XE_WARN_ON(!xe_uc_fw_is_loadable(&gsc->fw) || !gsc->q || gsc_fw_is_loaded(gt)))
@@ -117,6 +118,23 @@ static int gsc_upload(struct xe_gsc *gsc)
 		return err;
 	}
 
+	/*
+	 * GSC is only killed by an FLR, so we need to trigger one on unload to
+	 * make sure we stop it. This is because we assign a chunk of memory to
+	 * the GSC as part of the FW load, so we need to make sure it stops
+	 * using it when we release it to the system on driver unload. Note that
+	 * this is not a problem of the unload per-se, because the GSC will not
+	 * touch that memory unless there are requests for it coming from the
+	 * driver; therefore, no accesses will happen while Xe is not loaded,
+	 * but if we re-load the driver then the GSC might wake up and try to
+	 * access that old memory location again.
+	 * Given that an FLR is a very disruptive action (see the FLR function
+	 * for details), we want to do it as the last action before releasing
+	 * the access to the MMIO bar, which means we need to do it as part of
+	 * mmio cleanup.
+	 */
+	xe->needs_flr_on_fini = true;
+
 	err = emit_gsc_upload(gsc);
 	if (err) {
 		xe_gt_err(gt, "Failed to emit GSC FW upload (%pe)\n", ERR_PTR(err));
-- 
2.41.0


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

* [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (7 preceding siblings ...)
  2023-10-27 22:29 ` [Intel-xe] [PATCH 08/12] drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-10-31  8:08   ` Kandpal, Suraj
  2023-11-13 19:59   ` John Harrison
  2023-10-27 22:29 ` [Intel-xe] [PATCH 10/12] drm/xe/gsc: Query GSC compatibility version Daniele Ceraolo Spurio
                   ` (6 subsequent siblings)
  15 siblings, 2 replies; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe

Communication with the GSC FW is done via input/output buffers, whose
addresses are provided via a GSCCS command. The buffers contain a
generic header and a client-specific packet (e.g. PXP, HDCP); the
clients don't care about the header format and/or the GSCCS command in
the batch, they only care about their client-specific header. This patch
therefore introduces helpers that allow the callers to automatically
fill in the input header, submit the GSCCS job and decode the output
header, to make it so that the caller only needs to worry about their
client-specific input and output messages.

NOTE: this patch by itself only adds the interface so it does nothing,
I've kept it separate for review but the plan is to squash it with the
follow up patch before merge, so that the interface and the user are
introduced at the same time.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Cc: Suraj Kandpal <suraj.kandpal@intel.com>
---
 drivers/gpu/drm/xe/Makefile                   |   1 +
 .../gpu/drm/xe/abi/gsc_command_header_abi.h   |  46 +++++
 .../gpu/drm/xe/instructions/xe_gsc_commands.h |   2 +
 drivers/gpu/drm/xe/xe_gsc_submit.c            | 170 ++++++++++++++++++
 drivers/gpu/drm/xe/xe_gsc_submit.h            |  30 ++++
 5 files changed, 249 insertions(+)
 create mode 100644 drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
 create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.c
 create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.h

diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 4a442dcf4d79..876c122ad63c 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -58,6 +58,7 @@ xe-y += xe_bb.o \
 	xe_force_wake.o \
 	xe_ggtt.o \
 	xe_gsc.o \
+	xe_gsc_submit.o \
 	xe_gt.o \
 	xe_gt_clock.o \
 	xe_gt_debugfs.o \
diff --git a/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
new file mode 100644
index 000000000000..a4c2646803b5
--- /dev/null
+++ b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _ABI_GSC_COMMAND_HEADER_ABI_H
+#define _ABI_GSC_COMMAND_HEADER_ABI_H
+
+#include <linux/types.h>
+
+struct intel_gsc_mtl_header {
+	u32 validity_marker;
+#define GSC_HECI_VALIDITY_MARKER 0xA578875A
+
+	u8 heci_client_id;
+
+	u8 reserved1;
+
+	u16 header_version;
+#define MTL_GSC_HEADER_VERSION 1
+
+	/* FW allows host to decide host_session handle as it sees fit. */
+	u64 host_session_handle;
+
+	/* handle generated by FW for messages that need to be re-submitted */
+	u64 gsc_message_handle;
+
+	u32 message_size; /* lower 20 bits only, upper 12 are reserved */
+
+	/*
+	 * Flags mask:
+	 * Bit 0: Pending
+	 * Bit 1: Session Cleanup;
+	 * Bits 2-15: Flags
+	 * Bits 16-31: Extension Size
+	 * According to internal spec flags are either input or output
+	 * we distinguish the flags using OUTFLAG or INFLAG
+	 */
+	u32 flags;
+#define GSC_OUTFLAG_MSG_PENDING	BIT(0)
+#define GSC_INFLAG_MSG_CLEANUP	BIT(1)
+
+	u32 status;
+} __packed;
+
+#endif
diff --git a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
index c7a833d7f965..f8949cad9d0f 100644
--- a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
+++ b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
@@ -28,6 +28,8 @@
 	REG_FIELD_PREP(GSC_OPCODE, op) | \
 	REG_FIELD_PREP(GSC_CMD_DATA_AND_LEN, dl))
 
+#define GSC_HECI_CMD_PKT __GSC_INSTR(0, 6)
+
 #define GSC_FW_LOAD __GSC_INSTR(1, 2)
 #define   GSC_FW_LOAD_LIMIT_VALID REG_BIT(31)
 
diff --git a/drivers/gpu/drm/xe/xe_gsc_submit.c b/drivers/gpu/drm/xe/xe_gsc_submit.c
new file mode 100644
index 000000000000..e96336ac4728
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_gsc_submit.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include "xe_gsc_submit.h"
+
+#include "abi/gsc_command_header_abi.h"
+#include "xe_bb.h"
+#include "xe_exec_queue.h"
+#include "xe_gt_printk.h"
+#include "xe_gt_types.h"
+#include "xe_map.h"
+#include "xe_sched_job.h"
+#include "instructions/xe_gsc_commands.h"
+#include "regs/xe_gsc_regs.h"
+
+#define GSC_HDR_SIZE (sizeof(struct intel_gsc_mtl_header)) /* shorthand define */
+
+#define mtl_gsc_header_wr(xe_, map_, offset_, field_, val_) \
+	xe_map_wr_field(xe_, map_, offset_, struct intel_gsc_mtl_header, field_, val_)
+
+#define mtl_gsc_header_rd(xe_, map_, offset_, field_) \
+	xe_map_rd_field(xe_, map_, offset_, struct intel_gsc_mtl_header, field_)
+
+static struct xe_gt *
+gsc_to_gt(struct xe_gsc *gsc)
+{
+	return container_of(gsc, struct xe_gt, uc.gsc);
+}
+
+/**
+ * xe_gsc_header_write - write the MTL GSC header in memory
+ * @xe: the Xe device
+ * @map: the iosys map to write to
+ * @offset: offset from the start of the map at which to write the header
+ * @heci_client_id: client id identifying the type of command (see abi for values)
+ * @host_session_id: host session ID of the caller
+ * @payload_size: size of the payload that follows the header
+ *
+ * Returns: offset memory location following the header
+ */
+u32 xe_gsc_emit_header(struct xe_device *xe, struct iosys_map *map, u32 offset,
+		       u8 heci_client_id, u64 host_session_id, u32 payload_size)
+{
+	xe_map_memset(xe, map, offset, 0, GSC_HDR_SIZE);
+
+	mtl_gsc_header_wr(xe, map, offset, validity_marker, GSC_HECI_VALIDITY_MARKER);
+	mtl_gsc_header_wr(xe, map, offset, heci_client_id, heci_client_id);
+	mtl_gsc_header_wr(xe, map, offset, host_session_handle, host_session_id);
+	mtl_gsc_header_wr(xe, map, offset, header_version, MTL_GSC_HEADER_VERSION);
+	mtl_gsc_header_wr(xe, map, offset, message_size, payload_size + GSC_HDR_SIZE);
+
+	return offset + GSC_HDR_SIZE;
+};
+
+/**
+ * xe_gsc_check_and_update_pending - check the pending bit and update the input
+ * header with the retry handle from the output header
+ * @xe: the Xe device
+ * @in: the iosys map containing the input buffer
+ * @offset_in: offset within the iosys at which the input buffer is located
+ * @out: the iosys map containing the output buffer
+ * @offset_out: offset within the iosys at which the output buffer is located
+ *
+ * Returns: true if the pending bit was set, false otherwise
+ */
+bool xe_gsc_check_and_update_pending(struct xe_device *xe,
+				     struct iosys_map *in, u32 offset_in,
+				     struct iosys_map *out, u32 offset_out)
+{
+	if (mtl_gsc_header_rd(xe, out, offset_out, flags) & GSC_OUTFLAG_MSG_PENDING) {
+		u64 handle = mtl_gsc_header_rd(xe, out, offset_out, gsc_message_handle);
+
+		mtl_gsc_header_wr(xe, in, offset_in, gsc_message_handle, handle);
+
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * xe_gsc_read_out_header - reads and validates the output header and returns
+ * the offset of the reply following the header
+ * @xe: the Xe device
+ * @map: the iosys map containing the output buffer
+ * @offset: offset within the iosys at which the output buffer is located
+ * @min_payload_size: minimum size of the message excluding the gsc header
+ * @payload_offset: optional pointer to be set to the payload offset
+ *
+ * Returns: -errno value on failure, 0 otherwise
+ */
+int xe_gsc_read_out_header(struct xe_device *xe,
+			   struct iosys_map *map, u32 offset,
+			   u32 min_payload_size,
+			   u32 *payload_offset)
+{
+	u32 marker = mtl_gsc_header_rd(xe, map, offset, validity_marker);
+	u32 size = mtl_gsc_header_rd(xe, map, offset, message_size);
+	u32 payload_size = size - GSC_HDR_SIZE;
+
+	if (marker != GSC_HECI_VALIDITY_MARKER)
+		return -EPROTO;
+
+	if (size < GSC_HDR_SIZE || payload_size < min_payload_size)
+		return -ENODATA;
+
+	if (payload_offset)
+		*payload_offset = offset + GSC_HDR_SIZE;
+
+	return 0;
+}
+
+/**
+ * xe_gsc_pkt_submit_kernel - submit a kernel heci pkt to the GSC
+ * @xe: the GSC uC
+ * @addr_in: GGTT address of the message to send to the GSC
+ * @size_in: size of the message to send to the GSC
+ * @addr_out: GGTT address for the GSC to write the reply to
+ * @size_out: size of the memory reserved for the reply
+ */
+int xe_gsc_pkt_submit_kernel(struct xe_gsc *gsc, u64 addr_in, u32 size_in,
+			     u64 addr_out, u32 size_out)
+{
+	struct xe_gt *gt = gsc_to_gt(gsc);
+	struct xe_bb *bb;
+	struct xe_sched_job *job;
+	struct dma_fence *fence;
+	long timeout;
+
+	if (size_in < GSC_HDR_SIZE)
+		return -ENODATA;
+
+	if (size_out < GSC_HDR_SIZE)
+		return -ENOMEM;
+
+	bb = xe_bb_new(gt, 8, false);
+	if (IS_ERR(bb))
+		return PTR_ERR(bb);
+
+	bb->cs[bb->len++] = GSC_HECI_CMD_PKT;
+	bb->cs[bb->len++] = lower_32_bits(addr_in);
+	bb->cs[bb->len++] = upper_32_bits(addr_in);
+	bb->cs[bb->len++] = size_in;
+	bb->cs[bb->len++] = lower_32_bits(addr_out);
+	bb->cs[bb->len++] = upper_32_bits(addr_out);
+	bb->cs[bb->len++] = size_out;
+	bb->cs[bb->len++] = 0;
+
+	job = xe_bb_create_job(gsc->q, bb);
+	if (IS_ERR(job)) {
+		xe_bb_free(bb, NULL);
+		return PTR_ERR(job);
+	}
+
+	xe_sched_job_arm(job);
+	fence = dma_fence_get(&job->drm.s_fence->finished);
+	xe_sched_job_push(job);
+
+	timeout = dma_fence_wait_timeout(fence, false, HZ);
+	dma_fence_put(fence);
+	xe_bb_free(bb, NULL);
+	if (timeout < 0)
+		return timeout;
+	else if (!timeout)
+		return -ETIME;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/xe/xe_gsc_submit.h b/drivers/gpu/drm/xe/xe_gsc_submit.h
new file mode 100644
index 000000000000..0801da5d446a
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_gsc_submit.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _XE_GSC_SUBMIT_H_
+#define _XE_GSC_SUBMIT_H_
+
+#include <linux/types.h>
+
+struct iosys_map;
+struct xe_device;
+struct xe_gsc;
+
+u32 xe_gsc_emit_header(struct xe_device *xe, struct iosys_map *map, u32 offset,
+		       u8 heci_client_id, u64 host_session_id, u32 payload_size);
+
+bool xe_gsc_check_and_update_pending(struct xe_device *xe,
+				     struct iosys_map *in, u32 offset_in,
+				     struct iosys_map *out, u32 offset_out);
+
+int xe_gsc_read_out_header(struct xe_device *xe,
+			   struct iosys_map *map, u32 offset,
+			   u32 min_payload_size,
+			   u32 *payload_offset);
+
+int xe_gsc_pkt_submit_kernel(struct xe_gsc *gsc, u64 addr_in, u32 size_in,
+			     u64 addr_out, u32 size_out);
+
+#endif
-- 
2.41.0


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

* [Intel-xe] [PATCH 10/12] drm/xe/gsc: Query GSC compatibility version
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (8 preceding siblings ...)
  2023-10-27 22:29 ` [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-11-13 20:10   ` John Harrison
  2023-10-27 22:29 ` [Intel-xe] [PATCH 11/12] drm/xe/gsc: Define GSCCS for MTL Daniele Ceraolo Spurio
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe

The version is obtained via a dedicated MKHI GSC command.
The compatibility version is what we want to match against for the GSC,
so we need to call the FW version checker after obtaining the version.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 .../gpu/drm/xe/abi/gsc_mkhi_commands_abi.h    | 39 +++++++++
 drivers/gpu/drm/xe/xe_gsc.c                   | 81 +++++++++++++++++++
 drivers/gpu/drm/xe/xe_uc_fw.c                 | 18 +++--
 drivers/gpu/drm/xe/xe_uc_fw.h                 |  1 +
 4 files changed, 133 insertions(+), 6 deletions(-)
 create mode 100644 drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h

diff --git a/drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h b/drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h
new file mode 100644
index 000000000000..ad4d041873ab
--- /dev/null
+++ b/drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _ABI_GSC_MKHI_COMMANDS_ABI_H
+#define _ABI_GSC_MKHI_COMMANDS_ABI_H
+
+#include <linux/types.h>
+
+/* Heci client ID for MKHI commands */
+#define HECI_MEADDRESS_MKHI 7
+
+/* Generic MKHI header */
+struct gsc_mkhi_header {
+	u8  group_id;
+	u8  command;
+	u8  reserved;
+	u8  result;
+} __packed;
+
+/* GFX_SRV commands */
+#define MKHI_GROUP_ID_GFX_SRV 0x30
+
+#define MKHI_GFX_SRV_GET_HOST_COMPATIBILITY_VERSION (0x42)
+
+struct gsc_get_compatibility_version_in {
+	struct gsc_mkhi_header header;
+} __packed;
+
+struct gsc_get_compatibility_version_out {
+	struct gsc_mkhi_header header;
+	u16 proj_major;
+	u16 compat_major;
+	u16 compat_minor;
+	u16 reserved[5];
+} __packed;
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
index edf74780322a..63323a53f77f 100644
--- a/drivers/gpu/drm/xe/xe_gsc.c
+++ b/drivers/gpu/drm/xe/xe_gsc.c
@@ -7,10 +7,12 @@
 
 #include <drm/drm_managed.h>
 
+#include "abi/gsc_mkhi_commands_abi.h"
 #include "xe_bb.h"
 #include "xe_bo.h"
 #include "xe_device.h"
 #include "xe_exec_queue.h"
+#include "xe_gsc_submit.h"
 #include "xe_gt.h"
 #include "xe_gt_printk.h"
 #include "xe_map.h"
@@ -89,6 +91,77 @@ static int emit_gsc_upload(struct xe_gsc *gsc)
 	return 0;
 }
 
+#define query_msg_wr(xe_, map_, offset_, field_, val_) \
+	xe_map_wr_field(xe_, map_, offset_, struct gsc_get_compatibility_version_in, field_, val_)
+#define query_msg_rd(xe_, map_, offset_, field_) \
+	xe_map_rd_field(xe_, map_, offset_, struct gsc_get_compatibility_version_out, field_)
+
+static u32 emit_version_query_msg(struct xe_device *xe, struct iosys_map *map, u32 wr_offset)
+{
+	xe_map_memset(xe, map, wr_offset, 0, sizeof(struct gsc_get_compatibility_version_in));
+
+	query_msg_wr(xe, map, wr_offset, header.group_id, MKHI_GROUP_ID_GFX_SRV);
+	query_msg_wr(xe, map, wr_offset, header.command, MKHI_GFX_SRV_GET_HOST_COMPATIBILITY_VERSION);
+
+	return wr_offset + sizeof(struct gsc_get_compatibility_version_in);
+}
+
+#define GSC_VER_PKT_SZ SZ_4K /* 4K each for input and output */
+static int query_compatibility_version(struct xe_gsc *gsc)
+{
+	struct xe_uc_fw_version *compatibility = &gsc->fw.versions.found[XE_UC_FW_VER_COMPATIBILITY];
+	struct xe_gt *gt = gsc_to_gt(gsc);
+	struct xe_tile *tile = gt_to_tile(gt);
+	struct xe_device *xe = gt_to_xe(gt);
+	struct xe_bo *bo;
+	u32 wr_offset;
+	u32 rd_offset;
+	u64 ggtt_offset;
+	int err;
+
+	bo = xe_bo_create_pin_map(xe, tile, NULL, GSC_VER_PKT_SZ * 2,
+			  ttm_bo_type_kernel,
+			  XE_BO_CREATE_SYSTEM_BIT |
+			  XE_BO_CREATE_GGTT_BIT);;
+	if (IS_ERR(bo)) {
+		xe_gt_err(gt, "failed to allocate bo for GSC version query\n");
+		return err;
+	}
+
+	ggtt_offset = xe_bo_ggtt_addr(bo);
+
+	wr_offset = xe_gsc_emit_header(xe, &bo->vmap, 0, HECI_MEADDRESS_MKHI, 0,
+				       sizeof(struct gsc_get_compatibility_version_in));
+	wr_offset = emit_version_query_msg(xe, &bo->vmap, wr_offset);
+
+	err = xe_gsc_pkt_submit_kernel(gsc, ggtt_offset, wr_offset,
+				       ggtt_offset + GSC_VER_PKT_SZ,
+				       GSC_VER_PKT_SZ);
+	if (err) {
+		xe_gt_err(gt,
+			  "failed to submit GSC request for compatibility version: %d\n",
+			  err);
+		goto out_bo;
+	}
+
+	err = xe_gsc_read_out_header(xe, &bo->vmap, GSC_VER_PKT_SZ,
+				     sizeof(struct gsc_get_compatibility_version_out),
+				     &rd_offset);
+	if (err) {
+		xe_gt_err(gt, "HuC: invalid GSC reply for version query (err=%d)\n", err);
+		return err;
+	}
+
+	compatibility->major = query_msg_rd(xe, &bo->vmap, rd_offset, compat_major);
+	compatibility->minor = query_msg_rd(xe, &bo->vmap, rd_offset, compat_minor);
+
+	xe_gt_info(gt, "found GSC cv%u.%u\n", compatibility->major, compatibility->minor);
+
+out_bo:
+	xe_bo_unpin_map_no_vm(bo);
+	return err;
+}
+
 static int gsc_fw_is_loaded(struct xe_gt *gt)
 {
 	return xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)) &
@@ -147,6 +220,14 @@ static int gsc_upload(struct xe_gsc *gsc)
 		return err;
 	}
 
+	err = query_compatibility_version(gsc);
+	if (err)
+		return err;
+
+	err = xe_uc_fw_check_version_requirements(&gsc->fw);
+	if (err)
+		return err;
+
 	xe_gt_dbg(gt, "GSC FW async load completed\n");
 
 	return 0;
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
index bb38a76eb4a6..f57476f57de9 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.c
+++ b/drivers/gpu/drm/xe/xe_uc_fw.c
@@ -224,8 +224,11 @@ uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw)
 			uc_fw->versions.wanted.minor = entries[i].minor;
 			uc_fw->full_ver_required = entries[i].full_ver_required;
 
-			/* compatibility version checking coming soon */
-			uc_fw->versions.wanted_type = XE_UC_FW_VER_RELEASE;
+			if (uc_fw->type == XE_UC_FW_TYPE_GSC)
+				uc_fw->versions.wanted_type = XE_UC_FW_VER_COMPATIBILITY;
+			else
+				uc_fw->versions.wanted_type = XE_UC_FW_VER_RELEASE;
+
 			break;
 		}
 	}
@@ -321,7 +324,7 @@ static void guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)
 	uc_fw->private_data_size = css->private_data_size;
 }
 
-static int uc_fw_check_version_requirements(struct xe_uc_fw *uc_fw)
+int xe_uc_fw_check_version_requirements(struct xe_uc_fw *uc_fw)
 {
 	struct xe_device *xe = uc_fw_to_xe(uc_fw);
 	struct xe_uc_fw_version *wanted = &uc_fw->versions.wanted;
@@ -678,9 +681,12 @@ int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
 			    "Using %s firmware from %s",
 			    xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
 
-	err = uc_fw_check_version_requirements(uc_fw);
-	if (err)
-		goto fail;
+	/* for GSC FW we want the compatibility version, which we query after load */
+	if (uc_fw->type != XE_UC_FW_TYPE_GSC) {
+		err = xe_uc_fw_check_version_requirements(uc_fw);
+		if (err)
+			goto fail;
+	}
 
 	obj = xe_bo_create_from_data(xe, tile, fw->data, fw->size,
 				     ttm_bo_type_kernel,
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.h b/drivers/gpu/drm/xe/xe_uc_fw.h
index d4682b0276e2..d0d17f61a4ce 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.h
+++ b/drivers/gpu/drm/xe/xe_uc_fw.h
@@ -17,6 +17,7 @@ struct drm_printer;
 int xe_uc_fw_init(struct xe_uc_fw *uc_fw);
 size_t xe_uc_fw_copy_rsa(struct xe_uc_fw *uc_fw, void *dst, u32 max_len);
 int xe_uc_fw_upload(struct xe_uc_fw *uc_fw, u32 offset, u32 dma_flags);
+int xe_uc_fw_check_version_requirements(struct xe_uc_fw *uc_fw);
 void xe_uc_fw_print(struct xe_uc_fw *uc_fw, struct drm_printer *p);
 
 static inline u32 xe_uc_fw_rsa_offset(struct xe_uc_fw *uc_fw)
-- 
2.41.0


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

* [Intel-xe] [PATCH 11/12] drm/xe/gsc: Define GSCCS for MTL
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (9 preceding siblings ...)
  2023-10-27 22:29 ` [Intel-xe] [PATCH 10/12] drm/xe/gsc: Query GSC compatibility version Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-11-13 20:23   ` John Harrison
  2023-10-27 22:29 ` [Intel-xe] [PATCH 12/12] drm/xe/gsc: Define GSC FW " Daniele Ceraolo Spurio
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe

Add the GSCCS to the media_xelpmp engine list. Note that since the
GSCCS is only used with the GSC FW, we can consider it disabled if we
don't have the FW available.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 drivers/gpu/drm/xe/xe_hw_engine.c | 20 ++++++++++++++++++++
 drivers/gpu/drm/xe/xe_pci.c       |  2 +-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
index b5b084590888..142783177e45 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine.c
+++ b/drivers/gpu/drm/xe/xe_hw_engine.c
@@ -26,6 +26,7 @@
 #include "xe_rtp.h"
 #include "xe_sched_job.h"
 #include "xe_tuning.h"
+#include "xe_uc_fw.h"
 #include "xe_wa.h"
 
 #define MAX_MMIO_BASES 3
@@ -610,6 +611,24 @@ static void read_compute_fuses(struct xe_gt *gt)
 		read_compute_fuses_from_dss(gt);
 }
 
+static void check_gsc_availability(struct xe_gt *gt)
+{
+	struct xe_device *xe = gt_to_xe(gt);
+
+	if (!(gt->info.engine_mask & BIT(XE_HW_ENGINE_GSCCS0)))
+		return;
+
+	/*
+	 * The GSCCS is only used to communicate with the GSC FW, so if we don't
+	 * have the FW there is nothing we need the engine for and can therefore
+	 * skip its initialization.
+	 */
+	if (!xe_uc_fw_is_available(&gt->uc.gsc.fw)) {
+		gt->info.engine_mask &= ~BIT(XE_HW_ENGINE_GSCCS0);
+		drm_info(&xe->drm, "gsccs disabled due to lack of FW\n");
+	}
+}
+
 int xe_hw_engines_init_early(struct xe_gt *gt)
 {
 	int i;
@@ -617,6 +636,7 @@ int xe_hw_engines_init_early(struct xe_gt *gt)
 	read_media_fuses(gt);
 	read_copy_fuses(gt);
 	read_compute_fuses(gt);
+	check_gsc_availability(gt);
 
 	BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT < XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN);
 	BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT > XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX);
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index 2fae45b9d88e..c09b51735ee4 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -197,7 +197,7 @@ static const struct xe_media_desc media_xelpmp = {
 	.name = "Xe_LPM+",
 	.hw_engine_mask =
 		BIT(XE_HW_ENGINE_VCS0) | BIT(XE_HW_ENGINE_VCS2) |
-		BIT(XE_HW_ENGINE_VECS0),	/* TODO: add GSC0 */
+		BIT(XE_HW_ENGINE_VECS0) | BIT(XE_HW_ENGINE_GSCCS0)
 };
 
 static const struct xe_media_desc media_xe2 = {
-- 
2.41.0


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

* [Intel-xe] [PATCH 12/12] drm/xe/gsc: Define GSC FW for MTL
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (10 preceding siblings ...)
  2023-10-27 22:29 ` [Intel-xe] [PATCH 11/12] drm/xe/gsc: Define GSCCS for MTL Daniele Ceraolo Spurio
@ 2023-10-27 22:29 ` Daniele Ceraolo Spurio
  2023-11-13 20:26   ` John Harrison
  2023-10-27 22:32 ` [Intel-xe] ✓ CI.Patch_applied: success for GSC FW loading Patchwork
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-27 22:29 UTC (permalink / raw)
  To: intel-xe

We track GSC FW based on its compatibility version, which is what
determines the interface it supports.
Also add a modparam override like the ones for GuC and HuC.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 drivers/gpu/drm/xe/xe_module.c |  5 +++++
 drivers/gpu/drm/xe/xe_module.h |  1 +
 drivers/gpu/drm/xe/xe_uc_fw.c  | 20 ++++++++++++--------
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_module.c b/drivers/gpu/drm/xe/xe_module.c
index 7194595e7f31..8df7aea64ad5 100644
--- a/drivers/gpu/drm/xe/xe_module.c
+++ b/drivers/gpu/drm/xe/xe_module.c
@@ -41,6 +41,11 @@ module_param_named_unsafe(huc_firmware_path, xe_huc_firmware_path, charp, 0400);
 MODULE_PARM_DESC(huc_firmware_path,
 		 "HuC firmware path to use instead of the default one - empty string disables");
 
+char *xe_gsc_firmware_path;
+module_param_named_unsafe(gsc_firmware_path, xe_gsc_firmware_path, charp, 0400);
+MODULE_PARM_DESC(huc_firmware_path,
+		 "GSC firmware path to use instead of the default one - empty string disables");
+
 char *xe_param_force_probe = CONFIG_DRM_XE_FORCE_PROBE;
 module_param_named_unsafe(force_probe, xe_param_force_probe, charp, 0400);
 MODULE_PARM_DESC(force_probe,
diff --git a/drivers/gpu/drm/xe/xe_module.h b/drivers/gpu/drm/xe/xe_module.h
index e1da1e9ca5cb..7f49f95630d5 100644
--- a/drivers/gpu/drm/xe/xe_module.h
+++ b/drivers/gpu/drm/xe/xe_module.h
@@ -12,4 +12,5 @@ extern u32 xe_force_vram_bar_size;
 extern int xe_guc_log_level;
 extern char *xe_guc_firmware_path;
 extern char *xe_huc_firmware_path;
+extern char *xe_gsc_firmware_path;
 extern char *xe_param_force_probe;
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
index f57476f57de9..c9360d918b96 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.c
+++ b/drivers/gpu/drm/xe/xe_uc_fw.c
@@ -121,6 +121,10 @@ struct fw_blobs_by_type {
 	fw_def(ROCKETLAKE,	no_ver(i915,	huc,		tgl))		\
 	fw_def(TIGERLAKE,	no_ver(i915,	huc,		tgl))
 
+/* for the GSC FW we match the compatibility version and not the release one */
+#define XE_GSC_FIRMWARE_DEFS(fw_def, major_ver)		\
+	fw_def(METEORLAKE,	major_ver(i915,	gsc,	mtl,	1, 0))
+
 #define MAKE_FW_PATH(dir__, uc__, shortname__, version__)			\
 	__stringify(dir__) "/" __stringify(shortname__) "_" __stringify(uc__) version__ ".bin"
 
@@ -155,6 +159,7 @@ XE_GUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
 		     fw_filename_mmp_ver, fw_filename_major_ver)
 XE_HUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
 		     fw_filename_mmp_ver, fw_filename_no_ver)
+XE_GSC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE, fw_filename_major_ver)
 
 static struct xe_gt *
 __uc_fw_to_gt(struct xe_uc_fw *uc_fw, enum xe_uc_fw_type type)
@@ -196,23 +201,19 @@ uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw)
 				     uc_fw_entry_mmp_ver,
 				     uc_fw_entry_no_ver)
 	};
+	static const struct uc_fw_entry entries_gsc[] = {
+		XE_GSC_FIRMWARE_DEFS(XE_UC_FW_ENTRY, uc_fw_entry_major_ver)
+	};
 	static const struct fw_blobs_by_type blobs_all[XE_UC_FW_NUM_TYPES] = {
 		[XE_UC_FW_TYPE_GUC] = { entries_guc, ARRAY_SIZE(entries_guc) },
 		[XE_UC_FW_TYPE_HUC] = { entries_huc, ARRAY_SIZE(entries_huc) },
+		[XE_UC_FW_TYPE_GSC] = { entries_gsc, ARRAY_SIZE(entries_gsc) },
 	};
 	static const struct uc_fw_entry *entries;
 	enum xe_platform p = xe->info.platform;
 	u32 count;
 	int i;
 
-	/*
-	 * GSC FW support is still not fully in place, so we're not defining
-	 * the FW blob yet because we don't want the driver to attempt to load
-	 * it until we're ready for it.
-	 */
-	if (uc_fw->type == XE_UC_FW_TYPE_GSC)
-		return;
-
 	xe_assert(xe, uc_fw->type < ARRAY_SIZE(blobs_all));
 	entries = blobs_all[uc_fw->type].entries;
 	count = blobs_all[uc_fw->type].count;
@@ -248,6 +249,9 @@ uc_fw_override(struct xe_uc_fw *uc_fw)
 	case XE_UC_FW_TYPE_HUC:
 		path_override = xe_huc_firmware_path;
 		break;
+	case XE_UC_FW_TYPE_GSC:
+		path_override = xe_gsc_firmware_path;
+		break;
 	default:
 		break;
 	}
-- 
2.41.0


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

* [Intel-xe] ✓ CI.Patch_applied: success for GSC FW loading
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (11 preceding siblings ...)
  2023-10-27 22:29 ` [Intel-xe] [PATCH 12/12] drm/xe/gsc: Define GSC FW " Daniele Ceraolo Spurio
@ 2023-10-27 22:32 ` Patchwork
  2023-10-27 22:32 ` [Intel-xe] ✗ CI.checkpatch: warning " Patchwork
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 56+ messages in thread
From: Patchwork @ 2023-10-27 22:32 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio; +Cc: intel-xe

== Series Details ==

Series: GSC FW loading
URL   : https://patchwork.freedesktop.org/series/125717/
State : success

== Summary ==

=== Applying kernel patches on branch 'drm-xe-next' with base: ===
Base commit: f24c46200 drm/xe: Fix WA 14010918519 write to wrong register
=== git am output follows ===
.git/rebase-apply/patch:83: new blank line at EOF.
+
warning: 1 line adds whitespace errors.
Applying: drm/xe: implement driver initiated function-reset
Applying: fixup! drm/xe/guc: Report submission version of GuC firmware
Applying: drm/xe/uc: Rework uC version tracking
Applying: drm/xe/gsc: Introduce GSC FW
Applying: drm/xe/gsc: Parse GSC FW header
Applying: drm/xe/gsc: GSC FW load
Applying: drm/xe/gsc: Implement WA 14015076503
Applying: drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload
Applying: drm/xe/gsc: Add an interface for GSC packet submissions
Applying: drm/xe/gsc: Query GSC compatibility version
Applying: drm/xe/gsc: Define GSCCS for MTL
Applying: drm/xe/gsc: Define GSC FW for MTL



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

* [Intel-xe] ✗ CI.checkpatch: warning for GSC FW loading
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (12 preceding siblings ...)
  2023-10-27 22:32 ` [Intel-xe] ✓ CI.Patch_applied: success for GSC FW loading Patchwork
@ 2023-10-27 22:32 ` Patchwork
  2023-11-13 20:29   ` John Harrison
  2023-10-27 22:33 ` [Intel-xe] ✗ CI.KUnit: failure " Patchwork
  2023-11-13 16:05 ` [Intel-xe] [PATCH 00/12] " Lucas De Marchi
  15 siblings, 1 reply; 56+ messages in thread
From: Patchwork @ 2023-10-27 22:32 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio; +Cc: intel-xe

== Series Details ==

Series: GSC FW loading
URL   : https://patchwork.freedesktop.org/series/125717/
State : warning

== Summary ==

+ KERNEL=/kernel
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools mt
Cloning into 'mt'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ git -C mt rev-list -n1 origin/master
63c2b6b160bca2df6efc7bc4cea6f442097d7854
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ git log -n1
commit bfb0ed12aee560b93dc3056de7832bcd95c6cb81
Author: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Date:   Fri Oct 27 15:29:26 2023 -0700

    drm/xe/gsc: Define GSC FW for MTL
    
    We track GSC FW based on its compatibility version, which is what
    determines the interface it supports.
    Also add a modparam override like the ones for GuC and HuC.
    
    Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
    Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
+ /mt/dim checkpatch f24c46200dc8fad700f51106e678d68d38496860 drm-intel
01e883a3a drm/xe: implement driver initiated function-reset
f88539d04 fixup! drm/xe/guc: Report submission version of GuC firmware
590a5b6a1 drm/xe/uc: Rework uC version tracking
-:206: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'p_' - possible side-effects?
#206: FILE: drivers/gpu/drm/xe/xe_uc_fw.c:528:
+#define print_uc_fw_version(p_, version_, prefix_, ...) \
+do { \
+	struct xe_uc_fw_version *ver_ = (version_); \
+	if (ver_->build) \
+		drm_printf(p_, prefix_ " version %u.%u.%u.%u\n", ##__VA_ARGS__, \
+			   ver_->major, ver_->minor, \
+			   ver_->patch, ver_->build); \
+	else \
+		drm_printf(p_, prefix_ " version %u.%u.%u\n", ##__VA_ARGS__, \
+			  ver_->major, ver_->minor, ver_->patch); \
+} while(0);

-:206: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'prefix_' - possible side-effects?
#206: FILE: drivers/gpu/drm/xe/xe_uc_fw.c:528:
+#define print_uc_fw_version(p_, version_, prefix_, ...) \
+do { \
+	struct xe_uc_fw_version *ver_ = (version_); \
+	if (ver_->build) \
+		drm_printf(p_, prefix_ " version %u.%u.%u.%u\n", ##__VA_ARGS__, \
+			   ver_->major, ver_->minor, \
+			   ver_->patch, ver_->build); \
+	else \
+		drm_printf(p_, prefix_ " version %u.%u.%u\n", ##__VA_ARGS__, \
+			  ver_->major, ver_->minor, ver_->patch); \
+} while(0);

-:206: WARNING:DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON: do {} while (0) macros should not be semicolon terminated
#206: FILE: drivers/gpu/drm/xe/xe_uc_fw.c:528:
+#define print_uc_fw_version(p_, version_, prefix_, ...) \
+do { \
+	struct xe_uc_fw_version *ver_ = (version_); \
+	if (ver_->build) \
+		drm_printf(p_, prefix_ " version %u.%u.%u.%u\n", ##__VA_ARGS__, \
+			   ver_->major, ver_->minor, \
+			   ver_->patch, ver_->build); \
+	else \
+		drm_printf(p_, prefix_ " version %u.%u.%u\n", ##__VA_ARGS__, \
+			  ver_->major, ver_->minor, ver_->patch); \
+} while(0);

-:216: ERROR:SPACING: space required before the open parenthesis '('
#216: FILE: drivers/gpu/drm/xe/xe_uc_fw.c:538:
+} while(0);

total: 1 errors, 1 warnings, 2 checks, 298 lines checked
790a1435c drm/xe/gsc: Introduce GSC FW
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
-:31: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#31: 
new file mode 100644

-:63: CHECK:UNNECESSARY_PARENTHESES: Unnecessary parentheses around 'gt != tile->media_gt'
#63: FILE: drivers/gpu/drm/xe/xe_gsc.c:28:
+	if (tile->media_gt && (gt != tile->media_gt)) {

-:231: CHECK:LINE_SPACING: Please use a blank line after function/struct/union/enum declarations
#231: FILE: drivers/gpu/drm/xe/xe_uc_fw_types.h:61:
 };
+#define XE_UC_FW_NUM_TYPES 3

total: 0 errors, 1 warnings, 2 checks, 186 lines checked
7f147cee3 drm/xe/gsc: Parse GSC FW header
-:48: ERROR:POINTER_LOCATION: "foo * bar" should be "foo *bar"
#48: FILE: drivers/gpu/drm/xe/xe_uc_fw.c:493:
+		struct xe_gsc * gsc = container_of(uc_fw, struct xe_gsc, fw);

total: 1 errors, 0 warnings, 0 checks, 235 lines checked
8220f5ca7 drm/xe/gsc: GSC FW load
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
-:24: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#24: 
new file mode 100644

-:360: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#360: FILE: drivers/gpu/drm/xe/xe_gsc.c:268:
+
+}

total: 0 errors, 1 warnings, 1 checks, 408 lines checked
65fcf37ec drm/xe/gsc: Implement WA 14015076503
-:96: WARNING:RETURN_VOID: void function return statements are not generally useful
#96: FILE: drivers/gpu/drm/xe/xe_gt.c:535:
+	return;
+}

total: 0 errors, 1 warnings, 0 checks, 100 lines checked
b70e25c8d drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload
4b7e69532 drm/xe/gsc: Add an interface for GSC packet submissions
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
-:38: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#38: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 261 lines checked
b0022f477 drm/xe/gsc: Query GSC compatibility version
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
-:14: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#14: 
new file mode 100644

-:89: WARNING:LONG_LINE: line length of 102 exceeds 100 columns
#89: FILE: drivers/gpu/drm/xe/xe_gsc.c:104:
+	query_msg_wr(xe, map, wr_offset, header.command, MKHI_GFX_SRV_GET_HOST_COMPATIBILITY_VERSION);

-:97: WARNING:LONG_LINE: line length of 101 exceeds 100 columns
#97: FILE: drivers/gpu/drm/xe/xe_gsc.c:112:
+	struct xe_uc_fw_version *compatibility = &gsc->fw.versions.found[XE_UC_FW_VER_COMPATIBILITY];

-:108: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#108: FILE: drivers/gpu/drm/xe/xe_gsc.c:123:
+	bo = xe_bo_create_pin_map(xe, tile, NULL, GSC_VER_PKT_SZ * 2,
+			  ttm_bo_type_kernel,

-:110: WARNING:ONE_SEMICOLON: Statements terminations use 1 semicolon
#110: FILE: drivers/gpu/drm/xe/xe_gsc.c:125:
+			  XE_BO_CREATE_GGTT_BIT);;

total: 0 errors, 4 warnings, 1 checks, 185 lines checked
55c932772 drm/xe/gsc: Define GSCCS for MTL
bfb0ed12a drm/xe/gsc: Define GSC FW for MTL



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

* [Intel-xe] ✗ CI.KUnit: failure for GSC FW loading
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (13 preceding siblings ...)
  2023-10-27 22:32 ` [Intel-xe] ✗ CI.checkpatch: warning " Patchwork
@ 2023-10-27 22:33 ` Patchwork
  2023-11-13 20:30   ` John Harrison
  2023-11-13 16:05 ` [Intel-xe] [PATCH 00/12] " Lucas De Marchi
  15 siblings, 1 reply; 56+ messages in thread
From: Patchwork @ 2023-10-27 22:33 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio; +Cc: intel-xe

== Series Details ==

Series: GSC FW loading
URL   : https://patchwork.freedesktop.org/series/125717/
State : failure

== Summary ==

+ trap cleanup EXIT
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
stty: 'standard input': Inappropriate ioctl for device
[22:32:58] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[22:33:02] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make ARCH=um O=.kunit --jobs=48
[22:33:23] Starting KUnit Kernel (1/1)...
[22:33:23] ============================================================
[22:33:23] ========================== xe_bo  ==========================
[22:33:23] [SKIPPED] xe_ccs_migrate_kunit
[22:33:23] [SKIPPED] xe_bo_evict_kunit
[22:33:23] ===================== [SKIPPED] xe_bo ======================
[22:33:23] ======================= xe_dma_buf  ========================
[22:33:23] [SKIPPED] xe_dma_buf_kunit
[22:33:23] =================== [SKIPPED] xe_dma_buf ===================
[22:33:23] ======================= xe_migrate  ========================
[22:33:23] [SKIPPED] xe_migrate_sanity_kunit
[22:33:23] =================== [SKIPPED] xe_migrate ===================
[22:33:23] ========================= xe_pci  ==========================
[22:33:23] [PASSED] xe_gmdid_graphics_ip
[22:33:23] # xe_gmdid_media_ip: ASSERTION FAILED at drivers/gpu/drm/xe/tests/xe_pci_test.c:45
[22:33:23] Expected mask == 0, but
[22:33:23]     mask == 67108864 (0x4000000)
[22:33:23] [FAILED] xe_gmdid_media_ip
[22:33:23] # xe_pci: pass:1 fail:1 skip:0 total:2
[22:33:23] # Totals: pass:1 fail:1 skip:0 total:2
[22:33:23] ===================== [FAILED] xe_pci ======================
[22:33:23] ========================= xe_rtp  ==========================
[22:33:23] ================== xe_rtp_process_tests  ===================
[22:33:23] [PASSED] coalesce-same-reg
[22:33:23] [PASSED] no-match-no-add
[22:33:23] [PASSED] no-match-no-add-multiple-rules
[22:33:23] [PASSED] two-regs-two-entries
[22:33:23] [PASSED] clr-one-set-other
[22:33:23] [PASSED] set-field
[22:33:23] [PASSED] conflict-duplicate
[22:33:23] [PASSED] conflict-not-disjoint
[22:33:23] [PASSED] conflict-reg-type
[22:33:23] ============== [PASSED] xe_rtp_process_tests ===============
[22:33:23] ===================== [PASSED] xe_rtp ======================
[22:33:23] ========================== xe_wa  ==========================
[22:33:23] ======================== xe_wa_gt  =========================
[22:33:23] [PASSED] TIGERLAKE (B0)
[22:33:23] [PASSED] DG1 (A0)
[22:33:23] [PASSED] DG1 (B0)
[22:33:23] [PASSED] ALDERLAKE_S (A0)
[22:33:23] [PASSED] ALDERLAKE_S (B0)
[22:33:23] [PASSED] ALDERLAKE_S (C0)
[22:33:23] [PASSED] ALDERLAKE_S (D0)
[22:33:23] [PASSED] ALDERLAKE_P (A0)
[22:33:23] [PASSED] ALDERLAKE_P (B0)
[22:33:23] [PASSED] ALDERLAKE_P (C0)
[22:33:23] [PASSED] ALDERLAKE_S_RPLS (D0)
[22:33:23] [PASSED] ALDERLAKE_P_RPLU (E0)
[22:33:23] [PASSED] DG2_G10 (A0)
[22:33:23] [PASSED] DG2_G10 (A1)
[22:33:23] [PASSED] DG2_G10 (B0)
[22:33:23] [PASSED] DG2_G10 (C0)
[22:33:23] [PASSED] DG2_G11 (A0)
[22:33:23] [PASSED] DG2_G11 (B0)
[22:33:23] [PASSED] DG2_G11 (B1)
[22:33:23] [PASSED] DG2_G12 (A0)
[22:33:23] [PASSED] DG2_G12 (A1)
[22:33:23] [PASSED] PVC (B0)
[22:33:23] [PASSED] PVC (B1)
[22:33:23] [PASSED] PVC (C0)
[22:33:23] ==================== [PASSED] xe_wa_gt =====================
[22:33:23] ====================== [PASSED] xe_wa ======================
[22:33:23] ============================================================
[22:33:23] Testing complete. Ran 39 tests: passed: 34, failed: 1, skipped: 4
[22:33:23] Elapsed time: 24.485s total, 4.192s configuring, 20.173s building, 0.098s running

+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



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

* Re: [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions
  2023-10-27 22:29 ` [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions Daniele Ceraolo Spurio
@ 2023-10-31  8:08   ` Kandpal, Suraj
  2023-10-31 19:29     ` Daniele Ceraolo Spurio
  2023-11-13 19:59   ` John Harrison
  1 sibling, 1 reply; 56+ messages in thread
From: Kandpal, Suraj @ 2023-10-31  8:08 UTC (permalink / raw)
  To: Ceraolo Spurio, Daniele, intel-xe@lists.freedesktop.org



> -----Original Message-----
> From: Ceraolo Spurio, Daniele <daniele.ceraolospurio@intel.com>
> Sent: Saturday, October 28, 2023 3:59 AM
> To: intel-xe@lists.freedesktop.org
> Cc: Ceraolo Spurio, Daniele <daniele.ceraolospurio@intel.com>; Teres Alexis,
> Alan Previn <alan.previn.teres.alexis@intel.com>; Kandpal, Suraj
> <suraj.kandpal@intel.com>
> Subject: [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet
> submissions
> 
> Communication with the GSC FW is done via input/output buffers, whose
> addresses are provided via a GSCCS command. The buffers contain a generic
> header and a client-specific packet (e.g. PXP, HDCP); the clients don't care
> about the header format and/or the GSCCS command in the batch, they only
> care about their client-specific header. This patch therefore introduces helpers
> that allow the callers to automatically fill in the input header, submit the GSCCS
> job and decode the output header, to make it so that the caller only needs to
> worry about their client-specific input and output messages.
> 
> NOTE: this patch by itself only adds the interface so it does nothing, I've kept it
> separate for review but the plan is to squash it with the follow up patch before
> merge, so that the interface and the user are introduced at the same time.
> 
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
> Cc: Suraj Kandpal <suraj.kandpal@intel.com>
> ---
>  drivers/gpu/drm/xe/Makefile                   |   1 +
>  .../gpu/drm/xe/abi/gsc_command_header_abi.h   |  46 +++++
>  .../gpu/drm/xe/instructions/xe_gsc_commands.h |   2 +
>  drivers/gpu/drm/xe/xe_gsc_submit.c            | 170 ++++++++++++++++++
>  drivers/gpu/drm/xe/xe_gsc_submit.h            |  30 ++++
>  5 files changed, 249 insertions(+)
>  create mode 100644 drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>  create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.c
>  create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.h
> 
> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index
> 4a442dcf4d79..876c122ad63c 100644
> --- a/drivers/gpu/drm/xe/Makefile
> +++ b/drivers/gpu/drm/xe/Makefile
> @@ -58,6 +58,7 @@ xe-y += xe_bb.o \
>  	xe_force_wake.o \
>  	xe_ggtt.o \
>  	xe_gsc.o \
> +	xe_gsc_submit.o \
>  	xe_gt.o \
>  	xe_gt_clock.o \
>  	xe_gt_debugfs.o \
> diff --git a/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
> b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
> new file mode 100644
> index 000000000000..a4c2646803b5
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
> @@ -0,0 +1,46 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef _ABI_GSC_COMMAND_HEADER_ABI_H
> +#define _ABI_GSC_COMMAND_HEADER_ABI_H
> +
> +#include <linux/types.h>
> +
> +struct intel_gsc_mtl_header {
> +	u32 validity_marker;
> +#define GSC_HECI_VALIDITY_MARKER 0xA578875A
> +
> +	u8 heci_client_id;

Also during adding this is i915 we had decided to add certain defines
As seen here below may be add them as well
        u8 heci_client_id;
#define HECI_MEADDRESS_MKHI 7
#define HECI_MEADDRESS_PROXY 10
#define HECI_MEADDRESS_PXP 17
#define HECI_MEADDRESS_HDCP 18

> +
> +	u8 reserved1;
> +
> +	u16 header_version;
> +#define MTL_GSC_HEADER_VERSION 1
> +
> +	/* FW allows host to decide host_session handle as it sees fit. */
> +	u64 host_session_handle;

Also during adding this is i915 we had decided to add certain masks for PXP and HDCP
As seen here below may be add the as well

/*
         * FW allows host to decide host_session handle
         * as it sees fit.
         * For intertracebility reserving select bits(60-63)
         * to differentiate caller-target subsystem
         * 0000 - HDCP
         * 0001 - PXP Single Session
         */
        u64 host_session_handle;
#define HOST_SESSION_MASK       REG_GENMASK64(63, 60)
#define HOST_SESSION_PXP_SINGLE BIT_ULL(60)


> +
> +	/* handle generated by FW for messages that need to be re-submitted
> */
> +	u64 gsc_message_handle;
> +
> +	u32 message_size; /* lower 20 bits only, upper 12 are reserved */
> +
> +	/*
> +	 * Flags mask:
> +	 * Bit 0: Pending
> +	 * Bit 1: Session Cleanup;
> +	 * Bits 2-15: Flags
> +	 * Bits 16-31: Extension Size
> +	 * According to internal spec flags are either input or output
> +	 * we distinguish the flags using OUTFLAG or INFLAG
> +	 */
> +	u32 flags;
> +#define GSC_OUTFLAG_MSG_PENDING	BIT(0)
> +#define GSC_INFLAG_MSG_CLEANUP	BIT(1)
> +
> +	u32 status;
> +} __packed;
> +
> +#endif
> diff --git a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
> b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
> index c7a833d7f965..f8949cad9d0f 100644
> --- a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
> +++ b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
> @@ -28,6 +28,8 @@
>  	REG_FIELD_PREP(GSC_OPCODE, op) | \
>  	REG_FIELD_PREP(GSC_CMD_DATA_AND_LEN, dl))
> 
> +#define GSC_HECI_CMD_PKT __GSC_INSTR(0, 6)
> +
>  #define GSC_FW_LOAD __GSC_INSTR(1, 2)
>  #define   GSC_FW_LOAD_LIMIT_VALID REG_BIT(31)
> 
> diff --git a/drivers/gpu/drm/xe/xe_gsc_submit.c
> b/drivers/gpu/drm/xe/xe_gsc_submit.c
> new file mode 100644
> index 000000000000..e96336ac4728
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_gsc_submit.c
> @@ -0,0 +1,170 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#include "xe_gsc_submit.h"
> +
> +#include "abi/gsc_command_header_abi.h"
> +#include "xe_bb.h"
> +#include "xe_exec_queue.h"
> +#include "xe_gt_printk.h"
> +#include "xe_gt_types.h"
> +#include "xe_map.h"
> +#include "xe_sched_job.h"
> +#include "instructions/xe_gsc_commands.h"
> +#include "regs/xe_gsc_regs.h"
> +
> +#define GSC_HDR_SIZE (sizeof(struct intel_gsc_mtl_header)) /* shorthand
> +define */
> +
> +#define mtl_gsc_header_wr(xe_, map_, offset_, field_, val_) \
> +	xe_map_wr_field(xe_, map_, offset_, struct intel_gsc_mtl_header,
> +field_, val_)
> +
> +#define mtl_gsc_header_rd(xe_, map_, offset_, field_) \
> +	xe_map_rd_field(xe_, map_, offset_, struct intel_gsc_mtl_header,
> +field_)
> +
> +static struct xe_gt *
> +gsc_to_gt(struct xe_gsc *gsc)
> +{
> +	return container_of(gsc, struct xe_gt, uc.gsc); }
> +
> +/**
> + * xe_gsc_header_write - write the MTL GSC header in memory

You have define xe_gsc_header_write up in comments but the actual
Function is still called xe_gsc_emit_header one of these names need to be changed

> + * @xe: the Xe device
> + * @map: the iosys map to write to
> + * @offset: offset from the start of the map at which to write the
> +header
> + * @heci_client_id: client id identifying the type of command (see abi
> +for values)
> + * @host_session_id: host session ID of the caller
> + * @payload_size: size of the payload that follows the header
> + *
> + * Returns: offset memory location following the header  */
> +u32 xe_gsc_emit_header(struct xe_device *xe, struct iosys_map *map, u32
> offset,
> +		       u8 heci_client_id, u64 host_session_id, u32 payload_size) {
> +	xe_map_memset(xe, map, offset, 0, GSC_HDR_SIZE);
> +
> +	mtl_gsc_header_wr(xe, map, offset, validity_marker,
> GSC_HECI_VALIDITY_MARKER);
> +	mtl_gsc_header_wr(xe, map, offset, heci_client_id, heci_client_id);
> +	mtl_gsc_header_wr(xe, map, offset, host_session_handle,
> host_session_id);

Also We OR the required host_session_handle with the appropriate mask 
Dedpending on client id as seen below:
host_session_id &= ~HOST_SESSION_MASK;
        if (host_session_id && heci_client_id == HECI_MEADDRESS_PXP)
                host_session_id |= HOST_SESSION_PXP_SINGLE;
any reason to move away from this as it was decided we will have it here in a common place

Regards,
Suraj Kandpal

> +	mtl_gsc_header_wr(xe, map, offset, header_version,
> MTL_GSC_HEADER_VERSION);
> +	mtl_gsc_header_wr(xe, map, offset, message_size, payload_size +
> +GSC_HDR_SIZE);
> +
> +	return offset + GSC_HDR_SIZE;
> +};
> +
> +/**
> + * xe_gsc_check_and_update_pending - check the pending bit and update
> +the input
> + * header with the retry handle from the output header
> + * @xe: the Xe device
> + * @in: the iosys map containing the input buffer
> + * @offset_in: offset within the iosys at which the input buffer is
> +located
> + * @out: the iosys map containing the output buffer
> + * @offset_out: offset within the iosys at which the output buffer is
> +located
> + *
> + * Returns: true if the pending bit was set, false otherwise  */ bool
> +xe_gsc_check_and_update_pending(struct xe_device *xe,
> +				     struct iosys_map *in, u32 offset_in,
> +				     struct iosys_map *out, u32 offset_out) {
> +	if (mtl_gsc_header_rd(xe, out, offset_out, flags) &
> GSC_OUTFLAG_MSG_PENDING) {
> +		u64 handle = mtl_gsc_header_rd(xe, out, offset_out,
> +gsc_message_handle);
> +
> +		mtl_gsc_header_wr(xe, in, offset_in, gsc_message_handle,
> handle);
> +
> +		return true;
> +	}
> +
> +	return false;
> +}
> +
> +/**
> + * xe_gsc_read_out_header - reads and validates the output header and
> +returns
> + * the offset of the reply following the header
> + * @xe: the Xe device
> + * @map: the iosys map containing the output buffer
> + * @offset: offset within the iosys at which the output buffer is
> +located
> + * @min_payload_size: minimum size of the message excluding the gsc
> +header
> + * @payload_offset: optional pointer to be set to the payload offset
> + *
> + * Returns: -errno value on failure, 0 otherwise  */ int
> +xe_gsc_read_out_header(struct xe_device *xe,
> +			   struct iosys_map *map, u32 offset,
> +			   u32 min_payload_size,
> +			   u32 *payload_offset)
> +{
> +	u32 marker = mtl_gsc_header_rd(xe, map, offset, validity_marker);
> +	u32 size = mtl_gsc_header_rd(xe, map, offset, message_size);
> +	u32 payload_size = size - GSC_HDR_SIZE;
> +
> +	if (marker != GSC_HECI_VALIDITY_MARKER)
> +		return -EPROTO;
> +
> +	if (size < GSC_HDR_SIZE || payload_size < min_payload_size)
> +		return -ENODATA;
> +
> +	if (payload_offset)
> +		*payload_offset = offset + GSC_HDR_SIZE;
> +
> +	return 0;
> +}
> +
> +/**
> + * xe_gsc_pkt_submit_kernel - submit a kernel heci pkt to the GSC
> + * @xe: the GSC uC
> + * @addr_in: GGTT address of the message to send to the GSC
> + * @size_in: size of the message to send to the GSC
> + * @addr_out: GGTT address for the GSC to write the reply to
> + * @size_out: size of the memory reserved for the reply  */ int
> +xe_gsc_pkt_submit_kernel(struct xe_gsc *gsc, u64 addr_in, u32 size_in,
> +			     u64 addr_out, u32 size_out)
> +{
> +	struct xe_gt *gt = gsc_to_gt(gsc);
> +	struct xe_bb *bb;
> +	struct xe_sched_job *job;
> +	struct dma_fence *fence;
> +	long timeout;
> +
> +	if (size_in < GSC_HDR_SIZE)
> +		return -ENODATA;
> +
> +	if (size_out < GSC_HDR_SIZE)
> +		return -ENOMEM;
> +
> +	bb = xe_bb_new(gt, 8, false);
> +	if (IS_ERR(bb))
> +		return PTR_ERR(bb);
> +
> +	bb->cs[bb->len++] = GSC_HECI_CMD_PKT;
> +	bb->cs[bb->len++] = lower_32_bits(addr_in);
> +	bb->cs[bb->len++] = upper_32_bits(addr_in);
> +	bb->cs[bb->len++] = size_in;
> +	bb->cs[bb->len++] = lower_32_bits(addr_out);
> +	bb->cs[bb->len++] = upper_32_bits(addr_out);
> +	bb->cs[bb->len++] = size_out;
> +	bb->cs[bb->len++] = 0;
> +
> +	job = xe_bb_create_job(gsc->q, bb);
> +	if (IS_ERR(job)) {
> +		xe_bb_free(bb, NULL);
> +		return PTR_ERR(job);
> +	}
> +
> +	xe_sched_job_arm(job);
> +	fence = dma_fence_get(&job->drm.s_fence->finished);
> +	xe_sched_job_push(job);
> +
> +	timeout = dma_fence_wait_timeout(fence, false, HZ);
> +	dma_fence_put(fence);
> +	xe_bb_free(bb, NULL);
> +	if (timeout < 0)
> +		return timeout;
> +	else if (!timeout)
> +		return -ETIME;
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/xe/xe_gsc_submit.h
> b/drivers/gpu/drm/xe/xe_gsc_submit.h
> new file mode 100644
> index 000000000000..0801da5d446a
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_gsc_submit.h
> @@ -0,0 +1,30 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef _XE_GSC_SUBMIT_H_
> +#define _XE_GSC_SUBMIT_H_
> +
> +#include <linux/types.h>
> +
> +struct iosys_map;
> +struct xe_device;
> +struct xe_gsc;
> +
> +u32 xe_gsc_emit_header(struct xe_device *xe, struct iosys_map *map, u32
> offset,
> +		       u8 heci_client_id, u64 host_session_id, u32 payload_size);
> +
> +bool xe_gsc_check_and_update_pending(struct xe_device *xe,
> +				     struct iosys_map *in, u32 offset_in,
> +				     struct iosys_map *out, u32 offset_out);
> +
> +int xe_gsc_read_out_header(struct xe_device *xe,
> +			   struct iosys_map *map, u32 offset,
> +			   u32 min_payload_size,
> +			   u32 *payload_offset);
> +
> +int xe_gsc_pkt_submit_kernel(struct xe_gsc *gsc, u64 addr_in, u32 size_in,
> +			     u64 addr_out, u32 size_out);
> +
> +#endif
> --
> 2.41.0


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

* Re: [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware
  2023-10-27 22:29 ` [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware Daniele Ceraolo Spurio
@ 2023-10-31 14:09   ` Andrzej Hajda
  2023-10-31 19:00     ` Daniele Ceraolo Spurio
  2023-11-07 23:07   ` John Harrison
  1 sibling, 1 reply; 56+ messages in thread
From: Andrzej Hajda @ 2023-10-31 14:09 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 28.10.2023 00:29, Daniele Ceraolo Spurio wrote:
> Major GuC versions greater than 70 will have the submission version in
> the herader irrespective of their minor version number.

header I guess.

> 
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: John Harrison <John.C.Harrison@Intel.com>
> Reviewed-by: Matthew Brost <matthew.brost@intel.com>
> ---
>   drivers/gpu/drm/xe/xe_uc_fw.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
> index 3032c4f148d4..91d4a2272ee7 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
> @@ -278,7 +278,7 @@ static void guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)
>   	xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);
>   	xe_gt_assert(gt, uc_fw->major_ver_found >= 70);
>   
> -	if (uc_fw->minor_ver_found >= 6) {
> +	if (uc_fw->major_ver_found > 70 || uc_fw->minor_ver_found >= 6) {

Shouldn't be major > 70 || (major == 70 && minor >=6) ?
Anyway working with such representation of version looks quite painful :)

Regards
Andrzej


>   		/* v70.6.0 adds CSS header support */
>   		guc->submission_state.version.major =
>   			FIELD_GET(CSS_SW_VERSION_UC_MAJOR,


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

* Re: [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware
  2023-10-31 14:09   ` Andrzej Hajda
@ 2023-10-31 19:00     ` Daniele Ceraolo Spurio
  0 siblings, 0 replies; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-31 19:00 UTC (permalink / raw)
  To: Andrzej Hajda, intel-xe



On 10/31/2023 7:09 AM, Andrzej Hajda wrote:
> On 28.10.2023 00:29, Daniele Ceraolo Spurio wrote:
>> Major GuC versions greater than 70 will have the submission version in
>> the herader irrespective of their minor version number.
>
> header I guess.
>
>>
>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> Cc: Matthew Brost <matthew.brost@intel.com>
>> Cc: John Harrison <John.C.Harrison@Intel.com>
>> Reviewed-by: Matthew Brost <matthew.brost@intel.com>
>> ---
>>   drivers/gpu/drm/xe/xe_uc_fw.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c 
>> b/drivers/gpu/drm/xe/xe_uc_fw.c
>> index 3032c4f148d4..91d4a2272ee7 100644
>> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
>> @@ -278,7 +278,7 @@ static void guc_read_css_info(struct xe_uc_fw 
>> *uc_fw, struct uc_css_header *css)
>>       xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);
>>       xe_gt_assert(gt, uc_fw->major_ver_found >= 70);
>>   -    if (uc_fw->minor_ver_found >= 6) {
>> +    if (uc_fw->major_ver_found > 70 || uc_fw->minor_ver_found >= 6) {
>
> Shouldn't be major > 70 || (major == 70 && minor >=6) ?

In Xe we don't support any GuC version below 70 (there is an assert 
above to enforce that), so in the second part of the OR we're guaranteed 
that major == 70 without having to check for it.

> Anyway working with such representation of version looks quite painful :)

Unfortunately the FWs don't guarantee that their version can fit in a 
u32 for easier comparisons :/

Daniele

>
> Regards
> Andrzej
>
>
>>           /* v70.6.0 adds CSS header support */
>>           guc->submission_state.version.major =
>>               FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
>


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

* Re: [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions
  2023-10-31  8:08   ` Kandpal, Suraj
@ 2023-10-31 19:29     ` Daniele Ceraolo Spurio
  2023-11-08  8:25       ` Kandpal, Suraj
  0 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-10-31 19:29 UTC (permalink / raw)
  To: Kandpal, Suraj, intel-xe@lists.freedesktop.org

[-- Attachment #1: Type: text/plain, Size: 14960 bytes --]



On 10/31/2023 1:08 AM, Kandpal, Suraj wrote:
>
>> -----Original Message-----
>> From: Ceraolo Spurio, Daniele<daniele.ceraolospurio@intel.com>
>> Sent: Saturday, October 28, 2023 3:59 AM
>> To:intel-xe@lists.freedesktop.org
>> Cc: Ceraolo Spurio, Daniele<daniele.ceraolospurio@intel.com>; Teres Alexis,
>> Alan Previn<alan.previn.teres.alexis@intel.com>; Kandpal, Suraj
>> <suraj.kandpal@intel.com>
>> Subject: [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet
>> submissions
>>
>> Communication with the GSC FW is done via input/output buffers, whose
>> addresses are provided via a GSCCS command. The buffers contain a generic
>> header and a client-specific packet (e.g. PXP, HDCP); the clients don't care
>> about the header format and/or the GSCCS command in the batch, they only
>> care about their client-specific header. This patch therefore introduces helpers
>> that allow the callers to automatically fill in the input header, submit the GSCCS
>> job and decode the output header, to make it so that the caller only needs to
>> worry about their client-specific input and output messages.
>>
>> NOTE: this patch by itself only adds the interface so it does nothing, I've kept it
>> separate for review but the plan is to squash it with the follow up patch before
>> merge, so that the interface and the user are introduced at the same time.
>>
>> Signed-off-by: Daniele Ceraolo Spurio<daniele.ceraolospurio@intel.com>
>> Cc: Alan Previn<alan.previn.teres.alexis@intel.com>
>> Cc: Suraj Kandpal<suraj.kandpal@intel.com>
>> ---
>>   drivers/gpu/drm/xe/Makefile                   |   1 +
>>   .../gpu/drm/xe/abi/gsc_command_header_abi.h   |  46 +++++
>>   .../gpu/drm/xe/instructions/xe_gsc_commands.h |   2 +
>>   drivers/gpu/drm/xe/xe_gsc_submit.c            | 170 ++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_gsc_submit.h            |  30 ++++
>>   5 files changed, 249 insertions(+)
>>   create mode 100644 drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.c
>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.h
>>
>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index
>> 4a442dcf4d79..876c122ad63c 100644
>> --- a/drivers/gpu/drm/xe/Makefile
>> +++ b/drivers/gpu/drm/xe/Makefile
>> @@ -58,6 +58,7 @@ xe-y += xe_bb.o \
>>   	xe_force_wake.o \
>>   	xe_ggtt.o \
>>   	xe_gsc.o \
>> +	xe_gsc_submit.o \
>>   	xe_gt.o \
>>   	xe_gt_clock.o \
>>   	xe_gt_debugfs.o \
>> diff --git a/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>> b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>> new file mode 100644
>> index 000000000000..a4c2646803b5
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>> @@ -0,0 +1,46 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2023 Intel Corporation
>> + */
>> +
>> +#ifndef _ABI_GSC_COMMAND_HEADER_ABI_H
>> +#define _ABI_GSC_COMMAND_HEADER_ABI_H
>> +
>> +#include <linux/types.h>
>> +
>> +struct intel_gsc_mtl_header {
>> +	u32 validity_marker;
>> +#define GSC_HECI_VALIDITY_MARKER 0xA578875A
>> +
>> +	u8 heci_client_id;
> Also during adding this is i915 we had decided to add certain defines
> As seen here below may be add them as well
>          u8 heci_client_id;
> #define HECI_MEADDRESS_MKHI 7
> #define HECI_MEADDRESS_PROXY 10
> #define HECI_MEADDRESS_PXP 17
> #define HECI_MEADDRESS_HDCP 18

Before answering the specific question here, let me explain why the 
design diverged compared to i915, as it will be relevant for further 
comments as well. One big difference in Xe is the way memory is 
accessed, which now requires the use of xe_map_<rd/wr>_field (instead of 
doing direct access via pointer dereference), for which I have created 
the mtl_gsc_header_<rd/wr> wrappers. This lead me to wanting to make 
sure that all accesses to the header are done in this file, so that we 
don't need to export the wrappers, as that would require including the 
memory paths as well and make things complicated; consequently, I don't 
want other files to have to include the gsc_command_header_abi.h file, 
as they should have no need to do any header manipulation.
If other files can't include the header, the client-specific defines 
need to be moved to the client-specific files. For example, 
HECI_MEADDRESS_MKHI is defined in gsc_mkhi_commands_abi.h in the next 
patch. I'd expect the other defines to also go in the respective _abi.h 
files.

>> +
>> +	u8 reserved1;
>> +
>> +	u16 header_version;
>> +#define MTL_GSC_HEADER_VERSION 1
>> +
>> +	/* FW allows host to decide host_session handle as it sees fit. */
>> +	u64 host_session_handle;
> Also during adding this is i915 we had decided to add certain masks for PXP and HDCP
> As seen here below may be add the as well
>
> /*
>           * FW allows host to decide host_session handle
>           * as it sees fit.
>           * For intertracebility reserving select bits(60-63)
>           * to differentiate caller-target subsystem
>           * 0000 - HDCP
>           * 0001 - PXP Single Session
>           */
>          u64 host_session_handle;
> #define HOST_SESSION_MASK       REG_GENMASK64(63, 60)
> #define HOST_SESSION_PXP_SINGLE BIT_ULL(60)

Given the greater separation of layers (as explained above), I don't 
think we should special case the common code based on the caller. If we 
want to set part of the session id based on the heci client, then we can 
just encode the whole heci_client_id (see below).

>
>> +
>> +	/* handle generated by FW for messages that need to be re-submitted
>> */
>> +	u64 gsc_message_handle;
>> +
>> +	u32 message_size; /* lower 20 bits only, upper 12 are reserved */
>> +
>> +	/*
>> +	 * Flags mask:
>> +	 * Bit 0: Pending
>> +	 * Bit 1: Session Cleanup;
>> +	 * Bits 2-15: Flags
>> +	 * Bits 16-31: Extension Size
>> +	 * According to internal spec flags are either input or output
>> +	 * we distinguish the flags using OUTFLAG or INFLAG
>> +	 */
>> +	u32 flags;
>> +#define GSC_OUTFLAG_MSG_PENDING	BIT(0)
>> +#define GSC_INFLAG_MSG_CLEANUP	BIT(1)
>> +
>> +	u32 status;
>> +} __packed;
>> +
>> +#endif
>> diff --git a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>> b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>> index c7a833d7f965..f8949cad9d0f 100644
>> --- a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>> +++ b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>> @@ -28,6 +28,8 @@
>>   	REG_FIELD_PREP(GSC_OPCODE, op) | \
>>   	REG_FIELD_PREP(GSC_CMD_DATA_AND_LEN, dl))
>>
>> +#define GSC_HECI_CMD_PKT __GSC_INSTR(0, 6)
>> +
>>   #define GSC_FW_LOAD __GSC_INSTR(1, 2)
>>   #define   GSC_FW_LOAD_LIMIT_VALID REG_BIT(31)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_gsc_submit.c
>> b/drivers/gpu/drm/xe/xe_gsc_submit.c
>> new file mode 100644
>> index 000000000000..e96336ac4728
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/xe_gsc_submit.c
>> @@ -0,0 +1,170 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2023 Intel Corporation
>> + */
>> +
>> +#include "xe_gsc_submit.h"
>> +
>> +#include "abi/gsc_command_header_abi.h"
>> +#include "xe_bb.h"
>> +#include "xe_exec_queue.h"
>> +#include "xe_gt_printk.h"
>> +#include "xe_gt_types.h"
>> +#include "xe_map.h"
>> +#include "xe_sched_job.h"
>> +#include "instructions/xe_gsc_commands.h"
>> +#include "regs/xe_gsc_regs.h"
>> +
>> +#define GSC_HDR_SIZE (sizeof(struct intel_gsc_mtl_header)) /* shorthand
>> +define */
>> +
>> +#define mtl_gsc_header_wr(xe_, map_, offset_, field_, val_) \
>> +	xe_map_wr_field(xe_, map_, offset_, struct intel_gsc_mtl_header,
>> +field_, val_)
>> +
>> +#define mtl_gsc_header_rd(xe_, map_, offset_, field_) \
>> +	xe_map_rd_field(xe_, map_, offset_, struct intel_gsc_mtl_header,
>> +field_)
>> +
>> +static struct xe_gt *
>> +gsc_to_gt(struct xe_gsc *gsc)
>> +{
>> +	return container_of(gsc, struct xe_gt, uc.gsc); }
>> +
>> +/**
>> + * xe_gsc_header_write - write the MTL GSC header in memory
> You have define xe_gsc_header_write up in comments but the actual
> Function is still called xe_gsc_emit_header one of these names need to be changed

will fix

>> + * @xe: the Xe device
>> + * @map: the iosys map to write to
>> + * @offset: offset from the start of the map at which to write the
>> +header
>> + * @heci_client_id: client id identifying the type of command (see abi
>> +for values)
>> + * @host_session_id: host session ID of the caller
>> + * @payload_size: size of the payload that follows the header
>> + *
>> + * Returns: offset memory location following the header  */
>> +u32 xe_gsc_emit_header(struct xe_device *xe, struct iosys_map *map, u32
>> offset,
>> +		       u8 heci_client_id, u64 host_session_id, u32 payload_size) {
>> +	xe_map_memset(xe, map, offset, 0, GSC_HDR_SIZE);
>> +
>> +	mtl_gsc_header_wr(xe, map, offset, validity_marker,
>> GSC_HECI_VALIDITY_MARKER);
>> +	mtl_gsc_header_wr(xe, map, offset, heci_client_id, heci_client_id);
>> +	mtl_gsc_header_wr(xe, map, offset, host_session_handle,
>> host_session_id);
> Also We OR the required host_session_handle with the appropriate mask
> Dedpending on client id as seen below:
> host_session_id &= ~HOST_SESSION_MASK;
>          if (host_session_id && heci_client_id == HECI_MEADDRESS_PXP)
>                  host_session_id |= HOST_SESSION_PXP_SINGLE;
> any reason to move away from this as it was decided we will have it here in a common place

Continuing from the comment above, this could become:

#define HOST_SESSION_MASK       REG_GENMASK64(63, 56)

xe_assert(xe, !(host_session_id & HOST_SESSION_MASK));

if (host_session_id)
	host_session_id |= FIELD_PREP(HOST_SESSION_MASK, heci_client_id);


That way we can identify the client that generated the session without 
having to special-case. Does that work for you?

Daniele

>
> Regards,
> Suraj Kandpal
>
>> +	mtl_gsc_header_wr(xe, map, offset, header_version,
>> MTL_GSC_HEADER_VERSION);
>> +	mtl_gsc_header_wr(xe, map, offset, message_size, payload_size +
>> +GSC_HDR_SIZE);
>> +
>> +	return offset + GSC_HDR_SIZE;
>> +};
>> +
>> +/**
>> + * xe_gsc_check_and_update_pending - check the pending bit and update
>> +the input
>> + * header with the retry handle from the output header
>> + * @xe: the Xe device
>> + * @in: the iosys map containing the input buffer
>> + * @offset_in: offset within the iosys at which the input buffer is
>> +located
>> + * @out: the iosys map containing the output buffer
>> + * @offset_out: offset within the iosys at which the output buffer is
>> +located
>> + *
>> + * Returns: true if the pending bit was set, false otherwise  */ bool
>> +xe_gsc_check_and_update_pending(struct xe_device *xe,
>> +				     struct iosys_map *in, u32 offset_in,
>> +				     struct iosys_map *out, u32 offset_out) {
>> +	if (mtl_gsc_header_rd(xe, out, offset_out, flags) &
>> GSC_OUTFLAG_MSG_PENDING) {
>> +		u64 handle = mtl_gsc_header_rd(xe, out, offset_out,
>> +gsc_message_handle);
>> +
>> +		mtl_gsc_header_wr(xe, in, offset_in, gsc_message_handle,
>> handle);
>> +
>> +		return true;
>> +	}
>> +
>> +	return false;
>> +}
>> +
>> +/**
>> + * xe_gsc_read_out_header - reads and validates the output header and
>> +returns
>> + * the offset of the reply following the header
>> + * @xe: the Xe device
>> + * @map: the iosys map containing the output buffer
>> + * @offset: offset within the iosys at which the output buffer is
>> +located
>> + * @min_payload_size: minimum size of the message excluding the gsc
>> +header
>> + * @payload_offset: optional pointer to be set to the payload offset
>> + *
>> + * Returns: -errno value on failure, 0 otherwise  */ int
>> +xe_gsc_read_out_header(struct xe_device *xe,
>> +			   struct iosys_map *map, u32 offset,
>> +			   u32 min_payload_size,
>> +			   u32 *payload_offset)
>> +{
>> +	u32 marker = mtl_gsc_header_rd(xe, map, offset, validity_marker);
>> +	u32 size = mtl_gsc_header_rd(xe, map, offset, message_size);
>> +	u32 payload_size = size - GSC_HDR_SIZE;
>> +
>> +	if (marker != GSC_HECI_VALIDITY_MARKER)
>> +		return -EPROTO;
>> +
>> +	if (size < GSC_HDR_SIZE || payload_size < min_payload_size)
>> +		return -ENODATA;
>> +
>> +	if (payload_offset)
>> +		*payload_offset = offset + GSC_HDR_SIZE;
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * xe_gsc_pkt_submit_kernel - submit a kernel heci pkt to the GSC
>> + * @xe: the GSC uC
>> + * @addr_in: GGTT address of the message to send to the GSC
>> + * @size_in: size of the message to send to the GSC
>> + * @addr_out: GGTT address for the GSC to write the reply to
>> + * @size_out: size of the memory reserved for the reply  */ int
>> +xe_gsc_pkt_submit_kernel(struct xe_gsc *gsc, u64 addr_in, u32 size_in,
>> +			     u64 addr_out, u32 size_out)
>> +{
>> +	struct xe_gt *gt = gsc_to_gt(gsc);
>> +	struct xe_bb *bb;
>> +	struct xe_sched_job *job;
>> +	struct dma_fence *fence;
>> +	long timeout;
>> +
>> +	if (size_in < GSC_HDR_SIZE)
>> +		return -ENODATA;
>> +
>> +	if (size_out < GSC_HDR_SIZE)
>> +		return -ENOMEM;
>> +
>> +	bb = xe_bb_new(gt, 8, false);
>> +	if (IS_ERR(bb))
>> +		return PTR_ERR(bb);
>> +
>> +	bb->cs[bb->len++] = GSC_HECI_CMD_PKT;
>> +	bb->cs[bb->len++] = lower_32_bits(addr_in);
>> +	bb->cs[bb->len++] = upper_32_bits(addr_in);
>> +	bb->cs[bb->len++] = size_in;
>> +	bb->cs[bb->len++] = lower_32_bits(addr_out);
>> +	bb->cs[bb->len++] = upper_32_bits(addr_out);
>> +	bb->cs[bb->len++] = size_out;
>> +	bb->cs[bb->len++] = 0;
>> +
>> +	job = xe_bb_create_job(gsc->q, bb);
>> +	if (IS_ERR(job)) {
>> +		xe_bb_free(bb, NULL);
>> +		return PTR_ERR(job);
>> +	}
>> +
>> +	xe_sched_job_arm(job);
>> +	fence = dma_fence_get(&job->drm.s_fence->finished);
>> +	xe_sched_job_push(job);
>> +
>> +	timeout = dma_fence_wait_timeout(fence, false, HZ);
>> +	dma_fence_put(fence);
>> +	xe_bb_free(bb, NULL);
>> +	if (timeout < 0)
>> +		return timeout;
>> +	else if (!timeout)
>> +		return -ETIME;
>> +
>> +	return 0;
>> +}
>> diff --git a/drivers/gpu/drm/xe/xe_gsc_submit.h
>> b/drivers/gpu/drm/xe/xe_gsc_submit.h
>> new file mode 100644
>> index 000000000000..0801da5d446a
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/xe_gsc_submit.h
>> @@ -0,0 +1,30 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2023 Intel Corporation
>> + */
>> +
>> +#ifndef _XE_GSC_SUBMIT_H_
>> +#define _XE_GSC_SUBMIT_H_
>> +
>> +#include <linux/types.h>
>> +
>> +struct iosys_map;
>> +struct xe_device;
>> +struct xe_gsc;
>> +
>> +u32 xe_gsc_emit_header(struct xe_device *xe, struct iosys_map *map, u32
>> offset,
>> +		       u8 heci_client_id, u64 host_session_id, u32 payload_size);
>> +
>> +bool xe_gsc_check_and_update_pending(struct xe_device *xe,
>> +				     struct iosys_map *in, u32 offset_in,
>> +				     struct iosys_map *out, u32 offset_out);
>> +
>> +int xe_gsc_read_out_header(struct xe_device *xe,
>> +			   struct iosys_map *map, u32 offset,
>> +			   u32 min_payload_size,
>> +			   u32 *payload_offset);
>> +
>> +int xe_gsc_pkt_submit_kernel(struct xe_gsc *gsc, u64 addr_in, u32 size_in,
>> +			     u64 addr_out, u32 size_out);
>> +
>> +#endif
>> --
>> 2.41.0

[-- Attachment #2: Type: text/html, Size: 16985 bytes --]

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

* Re: [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware
  2023-10-27 22:29 ` [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware Daniele Ceraolo Spurio
  2023-10-31 14:09   ` Andrzej Hajda
@ 2023-11-07 23:07   ` John Harrison
  2023-11-07 23:24     ` Daniele Ceraolo Spurio
  1 sibling, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-07 23:07 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> Major GuC versions greater than 70 will have the submission version in
> the herader irrespective of their minor version number.
>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: John Harrison <John.C.Harrison@Intel.com>
> Reviewed-by: Matthew Brost <matthew.brost@intel.com>
> ---
>   drivers/gpu/drm/xe/xe_uc_fw.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
> index 3032c4f148d4..91d4a2272ee7 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
> @@ -278,7 +278,7 @@ static void guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)
>   	xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);
>   	xe_gt_assert(gt, uc_fw->major_ver_found >= 70);
>   
> -	if (uc_fw->minor_ver_found >= 6) {
> +	if (uc_fw->major_ver_found > 70 || uc_fw->minor_ver_found >= 6) {
I strongly recommend that we update to a newer version than 70.5.x for 
all platforms and then just drop all this code before Xe goes live. 
There is no need to be carrying this legacy hack in the shiny new clean 
driver!

John.

>   		/* v70.6.0 adds CSS header support */
>   		guc->submission_state.version.major =
>   			FIELD_GET(CSS_SW_VERSION_UC_MAJOR,


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

* Re: [Intel-xe] [PATCH 03/12] drm/xe/uc: Rework uC version tracking
  2023-10-27 22:29 ` [Intel-xe] [PATCH 03/12] drm/xe/uc: Rework uC version tracking Daniele Ceraolo Spurio
@ 2023-11-07 23:20   ` John Harrison
  0 siblings, 0 replies; 56+ messages in thread
From: John Harrison @ 2023-11-07 23:20 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> The GSC firmware, support for which is coming soon for Xe, has both a
> release version (updated on every release) and a compatibility version
> (update only on interface changes). The GuC has something similar, with
> a global release version and a submission version (which is also known
> as the VF compatibility version). The main difference is that for the
> GuC we still want to check the driver requirement against the release
> version, while for the GSC we'll need to check against the compatibility
> version.
> Instead of special casing the GSC, this patch reworks the FW logic so
> that we store both versions at the uc_fw level for all binaries and we
> allow checking against either of the versions. Initially, we'll use it
> to support GSC, but the logic could be re-used to allow VFs to check
> against the GuC compatibility version.
> Note that the GSC version has 4 numbers (major, minor, hotfix, build),
> so support for that has been added as part of the rework and will be
> used in follow-up patches.
>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: John Harrison <John.C.Harrison@Intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> ---
>   drivers/gpu/drm/xe/xe_guc_types.h   |   9 --
>   drivers/gpu/drm/xe/xe_uc_fw.c       | 141 +++++++++++++++++-----------
>   drivers/gpu/drm/xe/xe_uc_fw_types.h |  35 +++++--
>   3 files changed, 110 insertions(+), 75 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_guc_types.h b/drivers/gpu/drm/xe/xe_guc_types.h
> index a5e58917a499..343cc39ce5bc 100644
> --- a/drivers/gpu/drm/xe/xe_guc_types.h
> +++ b/drivers/gpu/drm/xe/xe_guc_types.h
> @@ -52,15 +52,6 @@ struct xe_guc {
>   			/** @seqno: suspend fences seqno */
>   			u32 seqno;
>   		} suspend;
> -		/** @version: submission version */
> -		struct {
> -			/** @major: major version of GuC submission */
> -			u32 major;
> -			/** @minor: minor version of GuC submission */
> -			u32 minor;
> -			/** @patch: patch version of GuC submission */
> -			u32 patch;
> -		} version;
>   		/** @enabled: submission is enabled */
>   		bool enabled;
>   	} submission_state;
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
> index 91d4a2272ee7..1f7dac394a1d 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
> @@ -204,9 +204,12 @@ uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw)
>   	for (i = 0; i < count && p <= entries[i].platform; i++) {
>   		if (p == entries[i].platform) {
>   			uc_fw->path = entries[i].path;
> -			uc_fw->major_ver_wanted = entries[i].major;
> -			uc_fw->minor_ver_wanted = entries[i].minor;
> +			uc_fw->versions.wanted.major = entries[i].major;
> +			uc_fw->versions.wanted.minor = entries[i].minor;
>   			uc_fw->full_ver_required = entries[i].full_ver_required;
> +
> +			/* compatibility version checking coming soon */
> +			uc_fw->versions.wanted_type = XE_UC_FW_VER_RELEASE;
>   			break;
>   		}
>   	}
> @@ -273,32 +276,30 @@ static void uc_fw_fini(struct drm_device *drm, void *arg)
>   static void guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)
>   {
>   	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
> -	struct xe_guc *guc = &gt->uc.guc;
> +	struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
> +	struct xe_uc_fw_version *compatibility = &uc_fw->versions.found[XE_UC_FW_VER_COMPATIBILITY];
>   
>   	xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);
> -	xe_gt_assert(gt, uc_fw->major_ver_found >= 70);
> +	xe_gt_assert(gt, release->major >= 70);
>   
> -	if (uc_fw->major_ver_found > 70 || uc_fw->minor_ver_found >= 6) {
> +	if (release->major > 70 || release->minor >= 6) {
>   		/* v70.6.0 adds CSS header support */
> -		guc->submission_state.version.major =
> -			FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
> -				  css->submission_version);
> -		guc->submission_state.version.minor =
> -			FIELD_GET(CSS_SW_VERSION_UC_MINOR,
> -				  css->submission_version);
> -		guc->submission_state.version.patch =
> -			FIELD_GET(CSS_SW_VERSION_UC_PATCH,
> -				  css->submission_version);
> -	} else if (uc_fw->minor_ver_found >= 3) {
> +		compatibility->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
> +						 css->submission_version);
> +		compatibility->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR,
> +						 css->submission_version);
> +		compatibility->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH,
> +						 css->submission_version);
> +	} else if (release->minor >= 3) {
>   		/* v70.3.0 introduced v1.1.0 */
> -		guc->submission_state.version.major = 1;
> -		guc->submission_state.version.minor = 1;
> -		guc->submission_state.version.patch = 0;
> +		compatibility->major = 1;
> +		compatibility->minor = 1;
> +		compatibility->patch = 0;
>   	} else {
>   		/* v70.0.0 introduced v1.0.0 */
> -		guc->submission_state.version.major = 1;
> -		guc->submission_state.version.minor = 0;
> -		guc->submission_state.version.patch = 0;
> +		compatibility->major = 1;
> +		compatibility->minor = 0;
> +		compatibility->patch = 0;
>   	}
As per comment on previous patch, this all needs to be removed. There is 
no need or reason to carry this legacy support in Xe.

Otherwise it all looks good.

John.


>   
>   	uc_fw->private_data_size = css->private_data_size;
> @@ -307,30 +308,31 @@ static void guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)
>   static int uc_fw_check_version_requirements(struct xe_uc_fw *uc_fw)
>   {
>   	struct xe_device *xe = uc_fw_to_xe(uc_fw);
> +	struct xe_uc_fw_version *wanted = &uc_fw->versions.wanted;
> +	struct xe_uc_fw_version *found = &uc_fw->versions.found[uc_fw->versions.wanted_type];
>   
>   	/* Driver has no requirement on any version, any is good. */
> -	if (!uc_fw->major_ver_wanted)
> +	if (!wanted->major)
>   		return 0;
>   
>   	/*
>   	 * If full version is required, both major and minor should match.
>   	 * Otherwise, at least the major version.
>   	 */
> -	if (uc_fw->major_ver_wanted != uc_fw->major_ver_found ||
> -	    (uc_fw->full_ver_required &&
> -	     uc_fw->minor_ver_wanted != uc_fw->minor_ver_found)) {
> +	if (wanted->major != found->major ||
> +	    (uc_fw->full_ver_required && wanted->minor != found->minor)) {
>   		drm_notice(&xe->drm, "%s firmware %s: unexpected version: %u.%u != %u.%u\n",
>   			   xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
> -			   uc_fw->major_ver_found, uc_fw->minor_ver_found,
> -			   uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
> +			   found->major, found->minor,
> +			   wanted->major, wanted->minor);
>   		goto fail;
>   	}
>   
> -	if (uc_fw->minor_ver_wanted > uc_fw->minor_ver_found) {
> +	if (wanted->minor > found->minor) {
>   		drm_notice(&xe->drm, "%s firmware (%u.%u) is recommended, but only (%u.%u) was found in %s\n",
>   			   xe_uc_fw_type_repr(uc_fw->type),
> -			   uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted,
> -			   uc_fw->major_ver_found, uc_fw->minor_ver_found,
> +			   wanted->major, wanted->minor,
> +			   found->major, found->minor,
>   			   uc_fw->path);
>   		drm_info(&xe->drm, "Consider updating your linux-firmware pkg or downloading from %s\n",
>   			 XE_UC_FIRMWARE_URL);
> @@ -349,6 +351,7 @@ static int uc_fw_check_version_requirements(struct xe_uc_fw *uc_fw)
>   static int parse_css_header(struct xe_uc_fw *uc_fw, const void *fw_data, size_t fw_size)
>   {
>   	struct xe_device *xe = uc_fw_to_xe(uc_fw);
> +	struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
>   	struct uc_css_header *css;
>   	size_t size;
>   
> @@ -390,12 +393,9 @@ static int parse_css_header(struct xe_uc_fw *uc_fw, const void *fw_data, size_t
>   	}
>   
>   	/* Get version numbers from the CSS header */
> -	uc_fw->major_ver_found = FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
> -					   css->sw_version);
> -	uc_fw->minor_ver_found = FIELD_GET(CSS_SW_VERSION_UC_MINOR,
> -					   css->sw_version);
> -	uc_fw->patch_ver_found = FIELD_GET(CSS_SW_VERSION_UC_PATCH,
> -					   css->sw_version);
> +	release->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR, css->sw_version);
> +	release->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR, css->sw_version);
> +	release->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH, css->sw_version);
>   
>   	if (uc_fw->type == XE_UC_FW_TYPE_GUC)
>   		guc_read_css_info(uc_fw, css);
> @@ -431,6 +431,7 @@ static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t siz
>   	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
>   	struct xe_device *xe = gt_to_xe(gt);
>   	const struct gsc_cpd_header_v2 *header = data;
> +	struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
>   	const struct gsc_manifest_header *manifest;
>   	size_t min_size = sizeof(*header);
>   	u32 offset;
> @@ -468,9 +469,9 @@ static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t siz
>   
>   	manifest = data + offset;
>   
> -	uc_fw->major_ver_found = manifest->fw_version.major;
> -	uc_fw->minor_ver_found = manifest->fw_version.minor;
> -	uc_fw->patch_ver_found = manifest->fw_version.hotfix;
> +	release->major = manifest->fw_version.major;
> +	release->minor = manifest->fw_version.minor;
> +	release->patch = manifest->fw_version.hotfix;
>   
>   	/* then optionally look for the css header */
>   	if (css_entry) {
> @@ -524,12 +525,25 @@ static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)
>   	return 0;
>   }
>   
> +#define print_uc_fw_version(p_, version_, prefix_, ...) \
> +do { \
> +	struct xe_uc_fw_version *ver_ = (version_); \
> +	if (ver_->build) \
> +		drm_printf(p_, prefix_ " version %u.%u.%u.%u\n", ##__VA_ARGS__, \
> +			   ver_->major, ver_->minor, \
> +			   ver_->patch, ver_->build); \
> +	else \
> +		drm_printf(p_, prefix_ " version %u.%u.%u\n", ##__VA_ARGS__, \
> +			  ver_->major, ver_->minor, ver_->patch); \
> +} while(0);
> +
>   int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
>   {
>   	struct xe_device *xe = uc_fw_to_xe(uc_fw);
>   	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
>   	struct xe_tile *tile = gt_to_tile(gt);
>   	struct device *dev = xe->drm.dev;
> +	struct drm_printer p = drm_info_printer(dev);
>   	const struct firmware *fw = NULL;
>   	struct xe_bo *obj;
>   	int err;
> @@ -567,9 +581,10 @@ int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
>   	if (err)
>   		goto fail;
>   
> -	drm_info(&xe->drm, "Using %s firmware from %s version %u.%u.%u\n",
> -		 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
> -		 uc_fw->major_ver_found, uc_fw->minor_ver_found, uc_fw->patch_ver_found);
> +	print_uc_fw_version(&p,
> +			    &uc_fw->versions.found[XE_UC_FW_VER_RELEASE],
> +			    "Using %s firmware from %s",
> +			    xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
>   
>   	err = uc_fw_check_version_requirements(uc_fw);
>   	if (err)
> @@ -686,26 +701,40 @@ int xe_uc_fw_upload(struct xe_uc_fw *uc_fw, u32 offset, u32 dma_flags)
>   	return err;
>   }
>   
> +static const char *version_type_repr(enum xe_uc_fw_version_types type)
> +{
> +	switch (type) {
> +	case XE_UC_FW_VER_RELEASE:
> +		return "release";
> +	case XE_UC_FW_VER_COMPATIBILITY:
> +		return "compatibility";
> +	default:
> +		return "Unknown version type";
> +	}
> +}
>   
>   void xe_uc_fw_print(struct xe_uc_fw *uc_fw, struct drm_printer *p)
>   {
> +	int i;
> +
>   	drm_printf(p, "%s firmware: %s\n",
>   		   xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
>   	drm_printf(p, "\tstatus: %s\n",
>   		   xe_uc_fw_status_repr(uc_fw->status));
> -	drm_printf(p, "\tversion: wanted %u.%u, found %u.%u.%u\n",
> -		   uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted,
> -		   uc_fw->major_ver_found, uc_fw->minor_ver_found, uc_fw->patch_ver_found);
> -	drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);
> -	drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);
> -
> -	if (uc_fw->type == XE_UC_FW_TYPE_GUC) {
> -		struct xe_gt *gt = uc_fw_to_gt(uc_fw);
> -		struct xe_guc *guc = &gt->uc.guc;
> -
> -		drm_printf(p, "\tSubmit version: %u.%u.%u\n",
> -			   guc->submission_state.version.major,
> -			   guc->submission_state.version.minor,
> -			   guc->submission_state.version.patch);
> +
> +	print_uc_fw_version(p, &uc_fw->versions.wanted, "\twanted %s",
> +			    version_type_repr(uc_fw->versions.wanted_type));
> +
> +	for (i = 0; i < XE_UC_FW_VER_TYPE_COUNT; i++) {
> +		struct xe_uc_fw_version *ver = &uc_fw->versions.found[i];
> +
> +		if (ver->major)
> +			print_uc_fw_version(p, ver, "\tfound %s",
> +					    version_type_repr(i));
>   	}
> +
> +	if (uc_fw->ucode_size)
> +		drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);
> +	if (uc_fw->rsa_size)
> +		drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);
>   }
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw_types.h b/drivers/gpu/drm/xe/xe_uc_fw_types.h
> index 1650599303c8..e4774c560e67 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw_types.h
> +++ b/drivers/gpu/drm/xe/xe_uc_fw_types.h
> @@ -59,6 +59,22 @@ enum xe_uc_fw_type {
>   };
>   #define XE_UC_FW_NUM_TYPES 2
>   
> +/**
> + * struct xe_uc_fw_version - Version for XE micro controller firmware
> + */
> +struct xe_uc_fw_version {
> +	u16 major;
> +	u16 minor;
> +	u16 patch;
> +	u16 build;
> +};
> +
> +enum xe_uc_fw_version_types {
> +	XE_UC_FW_VER_RELEASE,
> +	XE_UC_FW_VER_COMPATIBILITY,
> +	XE_UC_FW_VER_TYPE_COUNT
> +};
> +
>   /**
>    * struct xe_uc_fw - XE micro controller firmware
>    */
> @@ -98,16 +114,15 @@ struct xe_uc_fw {
>   	 * version required per platform.
>   	 */
>   
> -	/** @major_ver_wanted: major firmware version wanted by platform */
> -	u16 major_ver_wanted;
> -	/** @minor_ver_wanted: minor firmware version wanted by platform */
> -	u16 minor_ver_wanted;
> -	/** @major_ver_found: major version found in firmware blob */
> -	u16 major_ver_found;
> -	/** @minor_ver_found: major version found in firmware blob */
> -	u16 minor_ver_found;
> -	/** @patch_ver_found: patch version found in firmware blob */
> -	u16 patch_ver_found;
> +	/** @versions: FW versions wanted and found */
> +	struct {
> +		/** @wanted: firmware version wanted by platform */
> +		struct xe_uc_fw_version wanted;
> +		/** @wanted_type: type of firmware version wanted (release vs compatibility) */
> +		enum xe_uc_fw_version_types wanted_type;
> +		/** @found: fw versions found in firmware blob */
> +		struct xe_uc_fw_version found[XE_UC_FW_VER_TYPE_COUNT];
> +	} versions;
>   
>   	/** @rsa_size: RSA size */
>   	u32 rsa_size;


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

* Re: [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware
  2023-11-07 23:07   ` John Harrison
@ 2023-11-07 23:24     ` Daniele Ceraolo Spurio
  2023-11-07 23:38       ` John Harrison
  0 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-07 23:24 UTC (permalink / raw)
  To: John Harrison, intel-xe



On 11/7/2023 3:07 PM, John Harrison wrote:
> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>> Major GuC versions greater than 70 will have the submission version in
>> the herader irrespective of their minor version number.
>>
>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> Cc: Matthew Brost <matthew.brost@intel.com>
>> Cc: John Harrison <John.C.Harrison@Intel.com>
>> Reviewed-by: Matthew Brost <matthew.brost@intel.com>
>> ---
>>   drivers/gpu/drm/xe/xe_uc_fw.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c 
>> b/drivers/gpu/drm/xe/xe_uc_fw.c
>> index 3032c4f148d4..91d4a2272ee7 100644
>> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
>> @@ -278,7 +278,7 @@ static void guc_read_css_info(struct xe_uc_fw 
>> *uc_fw, struct uc_css_header *css)
>>       xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);
>>       xe_gt_assert(gt, uc_fw->major_ver_found >= 70);
>>   -    if (uc_fw->minor_ver_found >= 6) {
>> +    if (uc_fw->major_ver_found > 70 || uc_fw->minor_ver_found >= 6) {
> I strongly recommend that we update to a newer version than 70.5.x for 
> all platforms and then just drop all this code before Xe goes live. 
> There is no need to be carrying this legacy hack in the shiny new 
> clean driver!

How do you guarantee that the user is running at least 70.6? They might 
have an old firmware package. We don't currently fail if the minor is 
too low, we just throw a warning, so the driver would still load but the 
compatibility would be left unset in that scenario. Or are you 
suggesting to just fail the load if GuC < 70.6 ?

Daniele

>
> John.
>
>>           /* v70.6.0 adds CSS header support */
>>           guc->submission_state.version.major =
>>               FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
>


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

* Re: [Intel-xe] [PATCH 04/12] drm/xe/gsc: Introduce GSC FW
  2023-10-27 22:29 ` [Intel-xe] [PATCH 04/12] drm/xe/gsc: Introduce GSC FW Daniele Ceraolo Spurio
@ 2023-11-07 23:26   ` John Harrison
  2023-11-07 23:32     ` Daniele Ceraolo Spurio
  0 siblings, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-07 23:26 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe



On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> Add the basic definitions and init function. Same as HuC, GSC is only
> supported on the media GT on MTL and newer platforms.
> Note that the GSC requires submission resources which can't be allocated
> during init (because we don't have the hwconfig yet), so it can't be
> marked as loadable at the end of the init function. The allocation of
> those resources will come in the patch that makes use of them to load
> the FW.
>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
> Cc: John Harrison <John.C.Harrison@Intel.com>
> ---
>   drivers/gpu/drm/xe/Makefile         |  1 +
>   drivers/gpu/drm/xe/xe_gsc.c         | 50 +++++++++++++++++++++++++++++
>   drivers/gpu/drm/xe/xe_gsc.h         | 13 ++++++++
>   drivers/gpu/drm/xe/xe_gsc_types.h   | 19 +++++++++++
>   drivers/gpu/drm/xe/xe_uc.c          |  9 ++++--
>   drivers/gpu/drm/xe/xe_uc_fw.c       | 21 ++++++++++--
>   drivers/gpu/drm/xe/xe_uc_fw.h       |  2 ++
>   drivers/gpu/drm/xe/xe_uc_fw_types.h |  5 +--
>   drivers/gpu/drm/xe/xe_uc_types.h    |  3 ++
>   9 files changed, 116 insertions(+), 7 deletions(-)
>   create mode 100644 drivers/gpu/drm/xe/xe_gsc.c
>   create mode 100644 drivers/gpu/drm/xe/xe_gsc.h
>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_types.h
>
> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
> index cee57681732d..474b6044d054 100644
> --- a/drivers/gpu/drm/xe/Makefile
> +++ b/drivers/gpu/drm/xe/Makefile
> @@ -57,6 +57,7 @@ xe-y += xe_bb.o \
>   	xe_exec_queue.o \
>   	xe_force_wake.o \
>   	xe_ggtt.o \
> +	xe_gsc.o \
>   	xe_gt.o \
>   	xe_gt_clock.o \
>   	xe_gt_debugfs.o \
> diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
> new file mode 100644
> index 000000000000..3f709577d73b
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_gsc.c
> @@ -0,0 +1,50 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#include "xe_gsc.h"
> +
> +#include "xe_device.h"
> +#include "xe_gt.h"
> +#include "xe_gt_printk.h"
> +#include "xe_uc_fw.h"
> +
> +static struct xe_gt *
> +gsc_to_gt(struct xe_gsc *gsc)
> +{
> +	return container_of(gsc, struct xe_gt, uc.gsc);
> +}
> +
> +int xe_gsc_init(struct xe_gsc *gsc)
> +{
> +	struct xe_gt *gt = gsc_to_gt(gsc);
> +	struct xe_tile *tile = gt_to_tile(gt);
> +	int ret;
> +
> +	gsc->fw.type = XE_UC_FW_TYPE_GSC;
> +
> +	/* The GSC uC is only available on the media GT */
> +	if (tile->media_gt && (gt != tile->media_gt)) {
> +		xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_NOT_SUPPORTED);
> +		return 0;
> +	}
> +
> +	/*
> +	 * GSC can be "not supported" where GuC is instead supported, so we
> +	 * don't want to fail if xe_uc_fw_init() returns an error due to that.
Not following this comment. Can you explain more?

> +	 * To avoid this problem, check the FW status before the return code.
> +	 */
> +	ret = xe_uc_fw_init(&gsc->fw);
> +	if (!xe_uc_fw_is_enabled(&gsc->fw))
> +		return 0;
> +	else if (ret)
> +		goto out;
> +
> +	return 0;
> +
> +out:
> +	xe_gt_err(gt, "GSC init failed with %d", ret);
> +	return ret;
> +}
> +
> diff --git a/drivers/gpu/drm/xe/xe_gsc.h b/drivers/gpu/drm/xe/xe_gsc.h
> new file mode 100644
> index 000000000000..baa7f21f4204
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_gsc.h
> @@ -0,0 +1,13 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef _XE_GSC_H_
> +#define _XE_GSC_H_
> +
> +#include "xe_gsc_types.h"
> +
> +int xe_gsc_init(struct xe_gsc *gsc);
> +
> +#endif
> diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h b/drivers/gpu/drm/xe/xe_gsc_types.h
> new file mode 100644
> index 000000000000..135f156e3736
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_gsc_types.h
> @@ -0,0 +1,19 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef _XE_GSC_TYPES_H_
> +#define _XE_GSC_TYPES_H_
> +
> +#include "xe_uc_fw_types.h"
> +
> +/**
> + * struct xe_gsc - GSC
> + */
> +struct xe_gsc {
> +	/** @fw: Generic uC firmware management */
> +	struct xe_uc_fw fw;
> +};
> +
> +#endif
> diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
> index 784f53c5f282..b67154c78dff 100644
> --- a/drivers/gpu/drm/xe/xe_uc.c
> +++ b/drivers/gpu/drm/xe/xe_uc.c
> @@ -6,6 +6,7 @@
>   #include "xe_uc.h"
>   
>   #include "xe_device.h"
> +#include "xe_gsc.h"
>   #include "xe_gt.h"
>   #include "xe_guc.h"
>   #include "xe_guc_pc.h"
> @@ -32,8 +33,8 @@ int xe_uc_init(struct xe_uc *uc)
>   	int ret;
>   
>   	/*
> -	 * We call the GuC/HuC init functions even if GuC submission is off to
> -	 * correctly move our tracking of the FW state to "disabled".
> +	 * We call the GuC/HuC/GSC init functions even if GuC submission is off
> +	 * to correctly move our tracking of the FW state to "disabled".
>   	 */
>   
>   	ret = xe_guc_init(&uc->guc);
> @@ -44,6 +45,10 @@ int xe_uc_init(struct xe_uc *uc)
>   	if (ret)
>   		goto err;
>   
> +	ret = xe_gsc_init(&uc->gsc);
> +	if (ret)
> +		goto err;
> +
>   	if (!xe_device_uc_enabled(uc_to_xe(uc)))
>   		return 0;
>   
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
> index 1f7dac394a1d..af3e5cba606f 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
> @@ -158,11 +158,18 @@ XE_HUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
>   static struct xe_gt *
>   __uc_fw_to_gt(struct xe_uc_fw *uc_fw, enum xe_uc_fw_type type)
>   {
> -	if (type == XE_UC_FW_TYPE_GUC)
> +	XE_WARN_ON(type >= XE_UC_FW_NUM_TYPES);
> +
> +	switch (type) {
> +	case XE_UC_FW_TYPE_GUC:
>   		return container_of(uc_fw, struct xe_gt, uc.guc.fw);
> +	case XE_UC_FW_TYPE_HUC:
> +		return container_of(uc_fw, struct xe_gt, uc.huc.fw);
> +	case XE_UC_FW_TYPE_GSC:
> +		return container_of(uc_fw, struct xe_gt, uc.gsc.fw);
> +	}
>   
> -	XE_WARN_ON(type != XE_UC_FW_TYPE_HUC);
> -	return container_of(uc_fw, struct xe_gt, uc.huc.fw);
> +	return NULL;
>   }
>   
>   static struct xe_gt *uc_fw_to_gt(struct xe_uc_fw *uc_fw)
> @@ -197,6 +204,14 @@ uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw)
>   	u32 count;
>   	int i;
>   
> +	/*
> +	 * GSC FW support is still not fully in place, so we're not defining
> +	 * the FW blob yet because we don't want the driver to attempt to load
> +	 * it until we're ready for it.
> +	 */
> +	if (uc_fw->type == XE_UC_FW_TYPE_GSC)
> +		return;
> +
>   	xe_assert(xe, uc_fw->type < ARRAY_SIZE(blobs_all));
>   	entries = blobs_all[uc_fw->type].entries;
>   	count = blobs_all[uc_fw->type].count;
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.h b/drivers/gpu/drm/xe/xe_uc_fw.h
> index 1d1a0c156cdf..d4682b0276e2 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw.h
> +++ b/drivers/gpu/drm/xe/xe_uc_fw.h
> @@ -96,6 +96,8 @@ static inline const char *xe_uc_fw_type_repr(enum xe_uc_fw_type type)
>   		return "GuC";
>   	case XE_UC_FW_TYPE_HUC:
>   		return "HuC";
> +	case XE_UC_FW_TYPE_GSC:
> +		return "GSC";
>   	}
>   	return "uC";
>   }
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw_types.h b/drivers/gpu/drm/xe/xe_uc_fw_types.h
> index e4774c560e67..239256bfdb07 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw_types.h
> +++ b/drivers/gpu/drm/xe/xe_uc_fw_types.h
> @@ -55,9 +55,10 @@ enum xe_uc_fw_status {
>   
>   enum xe_uc_fw_type {
>   	XE_UC_FW_TYPE_GUC = 0,
> -	XE_UC_FW_TYPE_HUC
> +	XE_UC_FW_TYPE_HUC,
> +	XE_UC_FW_TYPE_GSC
>   };
> -#define XE_UC_FW_NUM_TYPES 2
> +#define XE_UC_FW_NUM_TYPES 3
Why is this not just a sentinel entry of the enum?

John.

>   
>   /**
>    * struct xe_uc_fw_version - Version for XE micro controller firmware
> diff --git a/drivers/gpu/drm/xe/xe_uc_types.h b/drivers/gpu/drm/xe/xe_uc_types.h
> index 49bef6498b85..9924e4484866 100644
> --- a/drivers/gpu/drm/xe/xe_uc_types.h
> +++ b/drivers/gpu/drm/xe/xe_uc_types.h
> @@ -6,6 +6,7 @@
>   #ifndef _XE_UC_TYPES_H_
>   #define _XE_UC_TYPES_H_
>   
> +#include "xe_gsc_types.h"
>   #include "xe_guc_types.h"
>   #include "xe_huc_types.h"
>   #include "xe_wopcm_types.h"
> @@ -18,6 +19,8 @@ struct xe_uc {
>   	struct xe_guc guc;
>   	/** @huc: HuC */
>   	struct xe_huc huc;
> +	/** @gsc: Graphics Security Controller */
> +	struct xe_gsc gsc;
>   	/** @wopcm: WOPCM */
>   	struct xe_wopcm wopcm;
>   };


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

* Re: [Intel-xe] [PATCH 04/12] drm/xe/gsc: Introduce GSC FW
  2023-11-07 23:26   ` John Harrison
@ 2023-11-07 23:32     ` Daniele Ceraolo Spurio
  2023-11-07 23:52       ` John Harrison
  0 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-07 23:32 UTC (permalink / raw)
  To: John Harrison, intel-xe



On 11/7/2023 3:26 PM, John Harrison wrote:
>
>
> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>> Add the basic definitions and init function. Same as HuC, GSC is only
>> supported on the media GT on MTL and newer platforms.
>> Note that the GSC requires submission resources which can't be allocated
>> during init (because we don't have the hwconfig yet), so it can't be
>> marked as loadable at the end of the init function. The allocation of
>> those resources will come in the patch that makes use of them to load
>> the FW.
>>
>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>> Cc: John Harrison <John.C.Harrison@Intel.com>
>> ---
>>   drivers/gpu/drm/xe/Makefile         |  1 +
>>   drivers/gpu/drm/xe/xe_gsc.c         | 50 +++++++++++++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_gsc.h         | 13 ++++++++
>>   drivers/gpu/drm/xe/xe_gsc_types.h   | 19 +++++++++++
>>   drivers/gpu/drm/xe/xe_uc.c          |  9 ++++--
>>   drivers/gpu/drm/xe/xe_uc_fw.c       | 21 ++++++++++--
>>   drivers/gpu/drm/xe/xe_uc_fw.h       |  2 ++
>>   drivers/gpu/drm/xe/xe_uc_fw_types.h |  5 +--
>>   drivers/gpu/drm/xe/xe_uc_types.h    |  3 ++
>>   9 files changed, 116 insertions(+), 7 deletions(-)
>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc.c
>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc.h
>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_types.h
>>
>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
>> index cee57681732d..474b6044d054 100644
>> --- a/drivers/gpu/drm/xe/Makefile
>> +++ b/drivers/gpu/drm/xe/Makefile
>> @@ -57,6 +57,7 @@ xe-y += xe_bb.o \
>>       xe_exec_queue.o \
>>       xe_force_wake.o \
>>       xe_ggtt.o \
>> +    xe_gsc.o \
>>       xe_gt.o \
>>       xe_gt_clock.o \
>>       xe_gt_debugfs.o \
>> diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
>> new file mode 100644
>> index 000000000000..3f709577d73b
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/xe_gsc.c
>> @@ -0,0 +1,50 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2023 Intel Corporation
>> + */
>> +
>> +#include "xe_gsc.h"
>> +
>> +#include "xe_device.h"
>> +#include "xe_gt.h"
>> +#include "xe_gt_printk.h"
>> +#include "xe_uc_fw.h"
>> +
>> +static struct xe_gt *
>> +gsc_to_gt(struct xe_gsc *gsc)
>> +{
>> +    return container_of(gsc, struct xe_gt, uc.gsc);
>> +}
>> +
>> +int xe_gsc_init(struct xe_gsc *gsc)
>> +{
>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>> +    struct xe_tile *tile = gt_to_tile(gt);
>> +    int ret;
>> +
>> +    gsc->fw.type = XE_UC_FW_TYPE_GSC;
>> +
>> +    /* The GSC uC is only available on the media GT */
>> +    if (tile->media_gt && (gt != tile->media_gt)) {
>> +        xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_NOT_SUPPORTED);
>> +        return 0;
>> +    }
>> +
>> +    /*
>> +     * GSC can be "not supported" where GuC is instead supported, so we
>> +     * don't want to fail if xe_uc_fw_init() returns an error due to 
>> that.
> Not following this comment. Can you explain more?

xe_uc_fw_init() is going to fail if the GSC FW is not defined for the 
platform. The uC switch is global for all FWs, so either all FW init 
functions are called or none of them; since we do have to handle the 
case where GuC is supported and GSC is not, xe_gsc_init() needs to not 
fail in that scenario. We do still have to call xe_uc_fw_init() as 
that's where the FW selection is (and therefore where we find out if it 
is defined or not), so the solution is to check the enablement status 
first before checking the return code.

>
>> +     * To avoid this problem, check the FW status before the return 
>> code.
>> +     */
>> +    ret = xe_uc_fw_init(&gsc->fw);
>> +    if (!xe_uc_fw_is_enabled(&gsc->fw))
>> +        return 0;
>> +    else if (ret)
>> +        goto out;
>> +
>> +    return 0;
>> +
>> +out:
>> +    xe_gt_err(gt, "GSC init failed with %d", ret);
>> +    return ret;
>> +}
>> +
>> diff --git a/drivers/gpu/drm/xe/xe_gsc.h b/drivers/gpu/drm/xe/xe_gsc.h
>> new file mode 100644
>> index 000000000000..baa7f21f4204
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/xe_gsc.h
>> @@ -0,0 +1,13 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2023 Intel Corporation
>> + */
>> +
>> +#ifndef _XE_GSC_H_
>> +#define _XE_GSC_H_
>> +
>> +#include "xe_gsc_types.h"
>> +
>> +int xe_gsc_init(struct xe_gsc *gsc);
>> +
>> +#endif
>> diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h 
>> b/drivers/gpu/drm/xe/xe_gsc_types.h
>> new file mode 100644
>> index 000000000000..135f156e3736
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/xe_gsc_types.h
>> @@ -0,0 +1,19 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2023 Intel Corporation
>> + */
>> +
>> +#ifndef _XE_GSC_TYPES_H_
>> +#define _XE_GSC_TYPES_H_
>> +
>> +#include "xe_uc_fw_types.h"
>> +
>> +/**
>> + * struct xe_gsc - GSC
>> + */
>> +struct xe_gsc {
>> +    /** @fw: Generic uC firmware management */
>> +    struct xe_uc_fw fw;
>> +};
>> +
>> +#endif
>> diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
>> index 784f53c5f282..b67154c78dff 100644
>> --- a/drivers/gpu/drm/xe/xe_uc.c
>> +++ b/drivers/gpu/drm/xe/xe_uc.c
>> @@ -6,6 +6,7 @@
>>   #include "xe_uc.h"
>>     #include "xe_device.h"
>> +#include "xe_gsc.h"
>>   #include "xe_gt.h"
>>   #include "xe_guc.h"
>>   #include "xe_guc_pc.h"
>> @@ -32,8 +33,8 @@ int xe_uc_init(struct xe_uc *uc)
>>       int ret;
>>         /*
>> -     * We call the GuC/HuC init functions even if GuC submission is 
>> off to
>> -     * correctly move our tracking of the FW state to "disabled".
>> +     * We call the GuC/HuC/GSC init functions even if GuC submission 
>> is off
>> +     * to correctly move our tracking of the FW state to "disabled".
>>        */
>>         ret = xe_guc_init(&uc->guc);
>> @@ -44,6 +45,10 @@ int xe_uc_init(struct xe_uc *uc)
>>       if (ret)
>>           goto err;
>>   +    ret = xe_gsc_init(&uc->gsc);
>> +    if (ret)
>> +        goto err;
>> +
>>       if (!xe_device_uc_enabled(uc_to_xe(uc)))
>>           return 0;
>>   diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c 
>> b/drivers/gpu/drm/xe/xe_uc_fw.c
>> index 1f7dac394a1d..af3e5cba606f 100644
>> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
>> @@ -158,11 +158,18 @@ XE_HUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
>>   static struct xe_gt *
>>   __uc_fw_to_gt(struct xe_uc_fw *uc_fw, enum xe_uc_fw_type type)
>>   {
>> -    if (type == XE_UC_FW_TYPE_GUC)
>> +    XE_WARN_ON(type >= XE_UC_FW_NUM_TYPES);
>> +
>> +    switch (type) {
>> +    case XE_UC_FW_TYPE_GUC:
>>           return container_of(uc_fw, struct xe_gt, uc.guc.fw);
>> +    case XE_UC_FW_TYPE_HUC:
>> +        return container_of(uc_fw, struct xe_gt, uc.huc.fw);
>> +    case XE_UC_FW_TYPE_GSC:
>> +        return container_of(uc_fw, struct xe_gt, uc.gsc.fw);
>> +    }
>>   -    XE_WARN_ON(type != XE_UC_FW_TYPE_HUC);
>> -    return container_of(uc_fw, struct xe_gt, uc.huc.fw);
>> +    return NULL;
>>   }
>>     static struct xe_gt *uc_fw_to_gt(struct xe_uc_fw *uc_fw)
>> @@ -197,6 +204,14 @@ uc_fw_auto_select(struct xe_device *xe, struct 
>> xe_uc_fw *uc_fw)
>>       u32 count;
>>       int i;
>>   +    /*
>> +     * GSC FW support is still not fully in place, so we're not 
>> defining
>> +     * the FW blob yet because we don't want the driver to attempt 
>> to load
>> +     * it until we're ready for it.
>> +     */
>> +    if (uc_fw->type == XE_UC_FW_TYPE_GSC)
>> +        return;
>> +
>>       xe_assert(xe, uc_fw->type < ARRAY_SIZE(blobs_all));
>>       entries = blobs_all[uc_fw->type].entries;
>>       count = blobs_all[uc_fw->type].count;
>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.h 
>> b/drivers/gpu/drm/xe/xe_uc_fw.h
>> index 1d1a0c156cdf..d4682b0276e2 100644
>> --- a/drivers/gpu/drm/xe/xe_uc_fw.h
>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.h
>> @@ -96,6 +96,8 @@ static inline const char *xe_uc_fw_type_repr(enum 
>> xe_uc_fw_type type)
>>           return "GuC";
>>       case XE_UC_FW_TYPE_HUC:
>>           return "HuC";
>> +    case XE_UC_FW_TYPE_GSC:
>> +        return "GSC";
>>       }
>>       return "uC";
>>   }
>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw_types.h 
>> b/drivers/gpu/drm/xe/xe_uc_fw_types.h
>> index e4774c560e67..239256bfdb07 100644
>> --- a/drivers/gpu/drm/xe/xe_uc_fw_types.h
>> +++ b/drivers/gpu/drm/xe/xe_uc_fw_types.h
>> @@ -55,9 +55,10 @@ enum xe_uc_fw_status {
>>     enum xe_uc_fw_type {
>>       XE_UC_FW_TYPE_GUC = 0,
>> -    XE_UC_FW_TYPE_HUC
>> +    XE_UC_FW_TYPE_HUC,
>> +    XE_UC_FW_TYPE_GSC
>>   };
>> -#define XE_UC_FW_NUM_TYPES 2
>> +#define XE_UC_FW_NUM_TYPES 3
> Why is this not just a sentinel entry of the enum?

No idea, I'm just updating the value. It is the same in i915.

Daniele

>
> John.
>
>>     /**
>>    * struct xe_uc_fw_version - Version for XE micro controller firmware
>> diff --git a/drivers/gpu/drm/xe/xe_uc_types.h 
>> b/drivers/gpu/drm/xe/xe_uc_types.h
>> index 49bef6498b85..9924e4484866 100644
>> --- a/drivers/gpu/drm/xe/xe_uc_types.h
>> +++ b/drivers/gpu/drm/xe/xe_uc_types.h
>> @@ -6,6 +6,7 @@
>>   #ifndef _XE_UC_TYPES_H_
>>   #define _XE_UC_TYPES_H_
>>   +#include "xe_gsc_types.h"
>>   #include "xe_guc_types.h"
>>   #include "xe_huc_types.h"
>>   #include "xe_wopcm_types.h"
>> @@ -18,6 +19,8 @@ struct xe_uc {
>>       struct xe_guc guc;
>>       /** @huc: HuC */
>>       struct xe_huc huc;
>> +    /** @gsc: Graphics Security Controller */
>> +    struct xe_gsc gsc;
>>       /** @wopcm: WOPCM */
>>       struct xe_wopcm wopcm;
>>   };
>


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

* Re: [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware
  2023-11-07 23:24     ` Daniele Ceraolo Spurio
@ 2023-11-07 23:38       ` John Harrison
  2023-11-09 19:59         ` Daniele Ceraolo Spurio
  0 siblings, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-07 23:38 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 11/7/2023 15:24, Daniele Ceraolo Spurio wrote:
> On 11/7/2023 3:07 PM, John Harrison wrote:
>> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>>> Major GuC versions greater than 70 will have the submission version in
>>> the herader irrespective of their minor version number.
>>>
>>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>>> Cc: Matthew Brost <matthew.brost@intel.com>
>>> Cc: John Harrison <John.C.Harrison@Intel.com>
>>> Reviewed-by: Matthew Brost <matthew.brost@intel.com>
>>> ---
>>>   drivers/gpu/drm/xe/xe_uc_fw.c | 2 +-
>>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c 
>>> b/drivers/gpu/drm/xe/xe_uc_fw.c
>>> index 3032c4f148d4..91d4a2272ee7 100644
>>> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
>>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
>>> @@ -278,7 +278,7 @@ static void guc_read_css_info(struct xe_uc_fw 
>>> *uc_fw, struct uc_css_header *css)
>>>       xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);
>>>       xe_gt_assert(gt, uc_fw->major_ver_found >= 70);
>>>   -    if (uc_fw->minor_ver_found >= 6) {
>>> +    if (uc_fw->major_ver_found > 70 || uc_fw->minor_ver_found >= 6) {
>> I strongly recommend that we update to a newer version than 70.5.x 
>> for all platforms and then just drop all this code before Xe goes 
>> live. There is no need to be carrying this legacy hack in the shiny 
>> new clean driver!
>
> How do you guarantee that the user is running at least 70.6? They 
> might have an old firmware package. We don't currently fail if the 
> minor is too low, we just throw a warning, so the driver would still 
> load but the compatibility would be left unset in that scenario. Or 
> are you suggesting to just fail the load if GuC < 70.6 ?
The only publicly supported platforms for Xe right now are LNL and 
later, aren't they? There is no GuC prior to 70.6 for LNL or later. And 
anything else is unofficial and for internal testing only.

But yeah, maybe go with >=70.6 or fail (it currently says >=70.0.0 or 
fail?) to be totally safe.

John.

>
> Daniele
>
>>
>> John.
>>
>>>           /* v70.6.0 adds CSS header support */
>>>           guc->submission_state.version.major =
>>>               FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
>>
>


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

* Re: [Intel-xe] [PATCH 05/12] drm/xe/gsc: Parse GSC FW header
  2023-10-27 22:29 ` [Intel-xe] [PATCH 05/12] drm/xe/gsc: Parse GSC FW header Daniele Ceraolo Spurio
@ 2023-11-07 23:45   ` John Harrison
  2023-11-07 23:57     ` Daniele Ceraolo Spurio
  0 siblings, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-07 23:45 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe; +Cc: Lucas De Marchi

On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> The GSC blob starts with a layout header, from which we can move to the
> boot directory, which in turns allows us to find the CPD. The CPD uses
> the same format as the one in the HuC binary, so we can re-use the same
> parsing code to get to the manifest, which contains the release and
> security versions of the FW.
>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
> Cc: John Harrison <John.C.Harrison@Intel.com>
> Cc: Lucas De Marchi <lucas.demarchi@intel.com>
> ---
>   drivers/gpu/drm/xe/xe_gsc_types.h |   3 +
>   drivers/gpu/drm/xe/xe_uc_fw.c     |  77 ++++++++++++++++++++
>   drivers/gpu/drm/xe/xe_uc_fw_abi.h | 113 ++++++++++++++++++++++++++++++
>   3 files changed, 193 insertions(+)
>
> diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h b/drivers/gpu/drm/xe/xe_gsc_types.h
> index 135f156e3736..1bc50583fe58 100644
> --- a/drivers/gpu/drm/xe/xe_gsc_types.h
> +++ b/drivers/gpu/drm/xe/xe_gsc_types.h
> @@ -14,6 +14,9 @@
>   struct xe_gsc {
>   	/** @fw: Generic uC firmware management */
>   	struct xe_uc_fw fw;
> +
> +	/** @security_version: SVN found in the fetched blob */
> +	u32 security_version;
There is no official structure to this version number?

>   };
>   
>   #endif
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
> index af3e5cba606f..bb38a76eb4a6 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
> @@ -12,6 +12,7 @@
>   #include "xe_bo.h"
>   #include "xe_device_types.h"
>   #include "xe_force_wake.h"
> +#include "xe_gsc.h"
>   #include "xe_gt.h"
>   #include "xe_map.h"
>   #include "xe_mmio.h"
> @@ -488,6 +489,13 @@ static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t siz
>   	release->minor = manifest->fw_version.minor;
>   	release->patch = manifest->fw_version.hotfix;
>   
> +	if (uc_fw->type == XE_UC_FW_TYPE_GSC) {
> +		struct xe_gsc * gsc = container_of(uc_fw, struct xe_gsc, fw);
> +
> +		release->build = manifest->fw_version.build;
> +		gsc->security_version = manifest->security_version;
> +	}
> +
>   	/* then optionally look for the css header */
>   	if (css_entry) {
>   		int ret;
> @@ -517,6 +525,73 @@ static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t siz
>   	return 0;
>   }
>   
> +static int parse_gsc_layout(struct xe_uc_fw *uc_fw, const void *data, size_t size)
> +{
> +	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
> +	const struct gsc_layout_pointers *layout = data;
> +	const struct gsc_bpdt_header *bpdt_header = NULL;
> +	const struct gsc_bpdt_entry *bpdt_entry = NULL;
> +	size_t min_size = sizeof(*layout);
> +	int i;
> +
> +	if (size < min_size) {
> +		xe_gt_err(gt, "GSC FW too small! %zu < %zu\n", size, min_size);
> +		return -ENODATA;
> +	}
> +
> +	min_size = layout->boot1.offset + layout->boot1.size;
> +	if (size < min_size) {
> +		xe_gt_err(gt, "GSC FW too small for boot section! %zu < %zu\n",
> +			  size, min_size);
> +		return -ENODATA;
> +	}
> +
> +	min_size = sizeof(*bpdt_header);
> +	if (layout->boot1.size < min_size) {
> +		xe_gt_err(gt, "GSC FW boot section too small for BPDT header: %u < %zu\n",
> +			  layout->boot1.size, min_size);
> +		return -ENODATA;
> +	}
> +
> +	bpdt_header = data + layout->boot1.offset;
> +	if (bpdt_header->signature != GSC_BPDT_HEADER_SIGNATURE) {
> +		xe_gt_err(gt, "invalid signature for BPDT header: 0x%08x!\n",
> +			  bpdt_header->signature);
> +		return -EINVAL;
> +	}
> +
> +	min_size += sizeof(*bpdt_entry) * bpdt_header->descriptor_count;
> +	if (layout->boot1.size < min_size) {
> +		xe_gt_err(gt, "GSC FW boot section too small for BPDT entries: %u < %zu\n",
> +			  layout->boot1.size, min_size);
> +		return -ENODATA;
> +	}
> +
> +	bpdt_entry = (void *)bpdt_header + sizeof(*bpdt_header);
> +	for (i = 0; i < bpdt_header->descriptor_count; i++, bpdt_entry++) {
> +		if ((bpdt_entry->type & GSC_BPDT_ENTRY_TYPE_MASK) !=
> +		    GSC_BPDT_ENTRY_TYPE_GSC_RBE)
> +			continue;
> +
> +		min_size = bpdt_entry->sub_partition_offset;
> +
> +		/* the CPD header parser will check that the CPD header fits */
> +		if (layout->boot1.size < min_size) {
> +			xe_gt_err(gt, "GSC FW boot section too small for CPD offset: %u < %zu\n",
> +				  layout->boot1.size, min_size);
> +			return -ENODATA;
> +		}
> +
> +		return parse_cpd_header(uc_fw,
> +					(void *)bpdt_header + min_size,
> +					layout->boot1.size - min_size,
Could compare this calculation against bpdt_entry->sub_partition_size 
before bothering to try to decode a partial CPD?

> +					"RBEP.man", NULL);
> +	}
> +
> +	xe_gt_err(gt, "couldn't find CPD header in GSC binary!\n");
> +	return -ENODATA;
> +}
> +
>   static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)
>   {
>   	int ret;
> @@ -526,6 +601,8 @@ static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)
>   	 * releases use GSC CPD headers.
>   	 */
>   	switch (uc_fw->type) {
> +	case XE_UC_FW_TYPE_GSC:
> +		return parse_gsc_layout(uc_fw, fw->data, fw->size);
>   	case XE_UC_FW_TYPE_HUC:
>   		ret = parse_cpd_header(uc_fw, fw->data, fw->size, "HUCP.man", "huc_fw");
>   		if (!ret || ret != -ENOENT)
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw_abi.h b/drivers/gpu/drm/xe/xe_uc_fw_abi.h
> index d6725c963251..edf2a448f4bb 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw_abi.h
> +++ b/drivers/gpu/drm/xe/xe_uc_fw_abi.h
> @@ -140,6 +140,58 @@ static_assert(sizeof(struct uc_css_header) == 128);
>    *	|      RSA Key (MTL+ only)                       |
>    *	|      ...                                       |
>    *	+================================================+
> + *
> + * The GSC binary starts instead with a layout header, which contains the
> + * locations of the various partitions of the binary. The one we're interested
> + * in is the boot1 partition, where we can find a BPDT header followed by
> + * entries, one of which points to the RBE sub-section of the partition, which
> + * contains the CPD. The GSC blob does not contain a CSS-based binary, so we
> + * only need to look for the manifest, which is under the "RBEP.man" CPD entry.
> + * Note that we have no need to find where the actual FW code is inside the
> + * image because the GSC ROM will itself parse the headers to find it and load
> + * it.
> + * The GSC firmware header layout looks like this::
> + *
> + *	+================================================+
> + *	|  Layout Pointers                               |
> + *	|      ...                                       |
> + *	|      Boot1 offset  >---------------------------|------o
> + *	|      ...                                       |      |
> + *	+================================================+      |
> + *	                                                        |
> + *	+================================================+      |
> + *	|  BPDT header                                   |<-----o
> + *	+================================================+
> + *	|  BPDT entries[]                                |
> + *	|      entry1                                    |
> + *	|      ...                                       |
> + *	|      entryX                                    |
> + *	|          type == GSC_RBE                       |
> + *	|          offset  >-----------------------------|------o
> + *	|      ...                                       |      |
> + *	+================================================+      |
> + *	                                                        |
> + *	+================================================+      |
> + *	|  CPD Header                                    |<-----o
> + *	+================================================+
> + *	|  CPD entries[]                                 |
> + *	|      entry1                                    |
> + *	|      ...                                       |
> + *	|      entryX                                    |
> + *	|          "RBEP.man"                            |
> + *	|           ...                                  |
> + *	|           offset  >----------------------------|------o
> + *	|      ...                                       |      |
> + *	+================================================+      |
> + *	                                                        |
> + *	+================================================+      |
> + *	| Manifest Header                                |<-----o
> + *	|  ...                                           |
> + *	|  FW version                                    |
> + *	|  ...                                           |
> + *	|  Security version                              |
> + *	|  ...                                           |
> + *	+================================================+
>    */
>   
>   struct gsc_version {
> @@ -149,6 +201,67 @@ struct gsc_version {
>   	u16 build;
>   } __packed;
>   
> +struct gsc_partition {
> +	u32 offset;
> +	u32 size;
> +} __packed;
> +
> +struct gsc_layout_pointers {
> +	u8 rom_bypass_vector[16];
> +
> +	/* size of pointers layout not including ROM bypass vector */
pointers layout -> layout pointers?

> +	u16 size;
> +
> +	/*
> +	 * bit0: Backup copy of layout pointers exist
exist -> exists

> +	 * bits1-15: reserved
> +	 */
> +	u8 flags;
> +
> +	u8 reserved;
> +
> +	u32 crc32;
Should we be doing anything to test against this crc or the one in the 
bpdt_header below?

John.

> +
> +	struct gsc_partition datap;
> +	struct gsc_partition boot1;
> +	struct gsc_partition boot2;
> +	struct gsc_partition boot3;
> +	struct gsc_partition boot4;
> +	struct gsc_partition boot5;
> +	struct gsc_partition temp_pages;
> +} __packed;
> +
> +/* Boot partition structures */
> +struct gsc_bpdt_header {
> +	u32 signature;
> +#define GSC_BPDT_HEADER_SIGNATURE 0x000055AA
> +
> +	u16 descriptor_count; /* num of entries after the header */
> +
> +	u8 version;
> +	u8 configuration;
> +
> +	u32 crc32;
> +
> +	u32 build_version;
> +	struct gsc_version tool_version;
> +} __packed;
> +
> +struct gsc_bpdt_entry {
> +	/*
> +	 * Bits 0-15: BPDT entry type
> +	 * Bits 16-17: reserved
> +	 * Bit 18: code sub-partition
> +	 * Bits 19-31: reserved
> +	 */
> +	u32 type;
> +#define GSC_BPDT_ENTRY_TYPE_MASK GENMASK(15, 0)
> +#define GSC_BPDT_ENTRY_TYPE_GSC_RBE 0x1
> +
> +	u32 sub_partition_offset; /* from the base of the BPDT header */
> +	u32 sub_partition_size;
> +} __packed;
> +
>   /* Code partition directory (CPD) structures */
>   struct gsc_cpd_header_v2 {
>   	u32 header_marker;


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

* Re: [Intel-xe] [PATCH 01/12] drm/xe: implement driver initiated function-reset
  2023-10-27 22:29 ` [Intel-xe] [PATCH 01/12] drm/xe: implement driver initiated function-reset Daniele Ceraolo Spurio
@ 2023-11-07 23:46   ` John Harrison
  2023-11-08 18:14     ` Daniele Ceraolo Spurio
  0 siblings, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-07 23:46 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe; +Cc: Andrzej Hajda

On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> From: Andrzej Hajda <andrzej.hajda@intel.com>
>
> Driver initiated function-reset (FLR) is the highest level of reset
> that we can trigger from within the driver. In contrast to PCI FLR it
> doesn't require re-enumeration of PCI BAR. It can be useful in case
> GT fails to reset. It is also the only way to trigger GSC reset from
> the driver and can be used in future addition of GSC support.
>
> v2:
>    - use regs from xe_regs.h
>    - move the flag to xe.mmio
>    - call flr only on root gt
>    - use BIOS protection check
>    - copy/paste comments from i915
> v3:
>    - flr code moved to xe_device.c
> v4:
>    - needs_flr_on_fini moved to xe_device
>
> Signed-off-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> ---
>   drivers/gpu/drm/xe/regs/xe_regs.h    |  7 +++
>   drivers/gpu/drm/xe/xe_device.c       | 78 ++++++++++++++++++++++++++++
>   drivers/gpu/drm/xe/xe_device_types.h |  3 ++
>   drivers/gpu/drm/xe/xe_gt.c           |  2 +
>   4 files changed, 90 insertions(+)
>
> diff --git a/drivers/gpu/drm/xe/regs/xe_regs.h b/drivers/gpu/drm/xe/regs/xe_regs.h
> index 2240cd157603..a646d13af03a 100644
> --- a/drivers/gpu/drm/xe/regs/xe_regs.h
> +++ b/drivers/gpu/drm/xe/regs/xe_regs.h
> @@ -57,8 +57,15 @@
>   
>   #define SOFTWARE_FLAGS_SPR33			XE_REG(0x4f084)
>   
> +#define GU_CNTL_PROTECTED			XE_REG(0x10100C)
> +#define   DRIVERINT_FLR_DIS			REG_BIT(31)
> +
>   #define GU_CNTL					XE_REG(0x101010)
>   #define   LMEM_INIT				REG_BIT(7)
> +#define   DRIVERFLR				REG_BIT(31)
> +
> +#define GU_DEBUG				XE_REG(0x101018)
> +#define   DRIVERFLR_STATUS			REG_BIT(31)
>   
>   #define XEHP_CLOCK_GATE_DIS			XE_REG(0x101014)
>   #define   SGSI_SIDECLK_DIS			REG_BIT(17)
> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
> index 8341acf66e5f..515cdf599fab 100644
> --- a/drivers/gpu/drm/xe/xe_device.c
> +++ b/drivers/gpu/drm/xe/xe_device.c
> @@ -5,6 +5,8 @@
>   
>   #include "xe_device.h"
>   
> +#include <linux/units.h>
> +
>   #include <drm/drm_aperture.h>
>   #include <drm/drm_atomic_helper.h>
>   #include <drm/drm_gem_ttm_helper.h>
> @@ -260,6 +262,78 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
>   	return ERR_PTR(err);
>   }
>   
> +/*
> + * The driver-initiated FLR is the highest level of reset that we can trigger
> + * from within the driver. It is different from the PCI FLR in that it doesn't
> + * fully reset the SGUnit and doesn't modify the PCI config space and therefore
> + * it doesn't require a re-enumeration of the PCI BARs. However, the
> + * driver-initiated FLR does still cause a reset of both GT and display and a
> + * memory wipe of local and stolen memory, so recovery would require a full HW
> + * re-init and saving/restoring (or re-populating) the wiped memory. Since we
> + * perform the FLR as the very last action before releasing access to the HW
> + * during the driver release flow, we don't attempt recovery at all, because
> + * if/when a new instance of i915 is bound to the device it will do a full
> + * re-init anyway.
> + */
> +static void xe_driver_flr(struct xe_device *xe)
> +{
> +	const unsigned int flr_timeout = 3 * MICRO; /* specs recommend a 3s wait */
3s or 3us?

And is it supposed to be the same timeout for both registers?

John.

> +	struct xe_gt *gt = xe_root_mmio_gt(xe);
> +	int ret;
> +
> +	if (xe_mmio_read32(gt, GU_CNTL_PROTECTED) & DRIVERINT_FLR_DIS) {
> +		drm_info_once(&xe->drm, "BIOS Disabled Driver-FLR\n");
> +		return;
> +	}
> +
> +	drm_dbg(&xe->drm, "Triggering Driver-FLR\n");
> +
> +	/*
> +	 * Make sure any pending FLR requests have cleared by waiting for the
> +	 * FLR trigger bit to go to zero. Also clear GU_DEBUG's DRIVERFLR_STATUS
> +	 * to make sure it's not still set from a prior attempt (it's a write to
> +	 * clear bit).
> +	 * Note that we should never be in a situation where a previous attempt
> +	 * is still pending (unless the HW is totally dead), but better to be
> +	 * safe in case something unexpected happens
> +	 */
> +	ret = xe_mmio_wait32(gt, GU_CNTL, DRIVERFLR, 0, flr_timeout, NULL, false);
> +	if (ret) {
> +		drm_err(&xe->drm, "Driver-FLR-prepare wait for ready failed! %d\n", ret);
> +		return;
> +	}
> +	xe_mmio_write32(gt, GU_DEBUG, DRIVERFLR_STATUS);
> +
> +	/* Trigger the actual Driver-FLR */
> +	xe_mmio_rmw32(gt, GU_CNTL, 0, DRIVERFLR);
> +
> +	/* Wait for hardware teardown to complete */
> +	ret = xe_mmio_wait32(gt, GU_CNTL, DRIVERFLR, 0, flr_timeout, NULL, false);
> +	if (ret) {
> +		drm_err(&xe->drm, "Driver-FLR-teardown wait completion failed! %d\n", ret);
> +		return;
> +	}
> +
> +	/* Wait for hardware/firmware re-init to complete */
> +	ret = xe_mmio_wait32(gt, GU_DEBUG, DRIVERFLR_STATUS, DRIVERFLR_STATUS,
> +			     flr_timeout, NULL, false);
> +	if (ret) {
> +		drm_err(&xe->drm, "Driver-FLR-reinit wait completion failed! %d\n", ret);
> +		return;
> +	}
> +
> +	/* Clear sticky completion status */
> +	xe_mmio_write32(gt, GU_DEBUG, DRIVERFLR_STATUS);
> +}
> +
> +static void xe_driver_flr_fini(struct drm_device *drm, void *arg)
> +{
> +	struct xe_device *xe = arg;
> +
> +	if (xe->needs_flr_on_fini)
> +		xe_driver_flr(xe);
> +}
> +
>   static void xe_device_sanitize(struct drm_device *drm, void *arg)
>   {
>   	struct xe_device *xe = arg;
> @@ -294,6 +368,10 @@ int xe_device_probe(struct xe_device *xe)
>   	if (err)
>   		return err;
>   
> +	err = drmm_add_action_or_reset(&xe->drm, xe_driver_flr_fini, xe);
> +	if (err)
> +		return err;
> +
>   	for_each_gt(gt, xe, id) {
>   		err = xe_pcode_probe(gt);
>   		if (err)
> diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
> index 44d622d4cc3a..9a0b0ccc1018 100644
> --- a/drivers/gpu/drm/xe/xe_device_types.h
> +++ b/drivers/gpu/drm/xe/xe_device_types.h
> @@ -405,6 +405,9 @@ struct xe_device {
>   	/** @heci_gsc: graphics security controller */
>   	struct xe_heci_gsc heci_gsc;
>   
> +	/** @needs_flr_on_fini: requests function-reset on fini */
> +	bool needs_flr_on_fini;
> +
>   	/* private: */
>   
>   #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
> diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
> index d380f67b3365..73c090762771 100644
> --- a/drivers/gpu/drm/xe/xe_gt.c
> +++ b/drivers/gpu/drm/xe/xe_gt.c
> @@ -626,6 +626,8 @@ static int gt_reset(struct xe_gt *gt)
>   	xe_uevent_gt_reset_failure(to_pci_dev(gt_to_xe(gt)->drm.dev),
>   				   gt_to_tile(gt)->id, gt->info.id);
>   
> +	gt_to_xe(gt)->needs_flr_on_fini = true;
> +
>   	return err;
>   }
>   


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

* Re: [Intel-xe] [PATCH 04/12] drm/xe/gsc: Introduce GSC FW
  2023-11-07 23:32     ` Daniele Ceraolo Spurio
@ 2023-11-07 23:52       ` John Harrison
  2023-11-07 23:59         ` Daniele Ceraolo Spurio
  0 siblings, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-07 23:52 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

[-- Attachment #1: Type: text/plain, Size: 10829 bytes --]

On 11/7/2023 15:32, Daniele Ceraolo Spurio wrote:
> On 11/7/2023 3:26 PM, John Harrison wrote:
>> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>>> Add the basic definitions and init function. Same as HuC, GSC is only
>>> supported on the media GT on MTL and newer platforms.
>>> Note that the GSC requires submission resources which can't be 
>>> allocated
>>> during init (because we don't have the hwconfig yet), so it can't be
>>> marked as loadable at the end of the init function. The allocation of
>>> those resources will come in the patch that makes use of them to load
>>> the FW.
>>>
>>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>>> Cc: John Harrison <John.C.Harrison@Intel.com>
>>> ---
>>>   drivers/gpu/drm/xe/Makefile         |  1 +
>>>   drivers/gpu/drm/xe/xe_gsc.c         | 50 
>>> +++++++++++++++++++++++++++++
>>>   drivers/gpu/drm/xe/xe_gsc.h         | 13 ++++++++
>>>   drivers/gpu/drm/xe/xe_gsc_types.h   | 19 +++++++++++
>>>   drivers/gpu/drm/xe/xe_uc.c          |  9 ++++--
>>>   drivers/gpu/drm/xe/xe_uc_fw.c       | 21 ++++++++++--
>>>   drivers/gpu/drm/xe/xe_uc_fw.h       |  2 ++
>>>   drivers/gpu/drm/xe/xe_uc_fw_types.h |  5 +--
>>>   drivers/gpu/drm/xe/xe_uc_types.h    |  3 ++
>>>   9 files changed, 116 insertions(+), 7 deletions(-)
>>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc.c
>>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc.h
>>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_types.h
>>>
>>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
>>> index cee57681732d..474b6044d054 100644
>>> --- a/drivers/gpu/drm/xe/Makefile
>>> +++ b/drivers/gpu/drm/xe/Makefile
>>> @@ -57,6 +57,7 @@ xe-y += xe_bb.o \
>>>       xe_exec_queue.o \
>>>       xe_force_wake.o \
>>>       xe_ggtt.o \
>>> +    xe_gsc.o \
>>>       xe_gt.o \
>>>       xe_gt_clock.o \
>>>       xe_gt_debugfs.o \
>>> diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
>>> new file mode 100644
>>> index 000000000000..3f709577d73b
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/xe/xe_gsc.c
>>> @@ -0,0 +1,50 @@
>>> +// SPDX-License-Identifier: MIT
>>> +/*
>>> + * Copyright © 2023 Intel Corporation
>>> + */
>>> +
>>> +#include "xe_gsc.h"
>>> +
>>> +#include "xe_device.h"
>>> +#include "xe_gt.h"
>>> +#include "xe_gt_printk.h"
>>> +#include "xe_uc_fw.h"
>>> +
>>> +static struct xe_gt *
>>> +gsc_to_gt(struct xe_gsc *gsc)
>>> +{
>>> +    return container_of(gsc, struct xe_gt, uc.gsc);
>>> +}
>>> +
>>> +int xe_gsc_init(struct xe_gsc *gsc)
>>> +{
>>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>>> +    struct xe_tile *tile = gt_to_tile(gt);
>>> +    int ret;
>>> +
>>> +    gsc->fw.type = XE_UC_FW_TYPE_GSC;
>>> +
>>> +    /* The GSC uC is only available on the media GT */
>>> +    if (tile->media_gt && (gt != tile->media_gt)) {
>>> +        xe_uc_fw_change_status(&gsc->fw, 
>>> XE_UC_FIRMWARE_NOT_SUPPORTED);
>>> +        return 0;
>>> +    }
>>> +
>>> +    /*
>>> +     * GSC can be "not supported" where GuC is instead supported, 
>>> so we
>>> +     * don't want to fail if xe_uc_fw_init() returns an error due 
>>> to that.
>> Not following this comment. Can you explain more?
>
> xe_uc_fw_init() is going to fail if the GSC FW is not defined for the 
> platform. The uC switch is global for all FWs, so either all FW init 
> functions are called or none of them; since we do have to handle the 
> case where GuC is supported and GSC is not, xe_gsc_init() needs to not 
> fail in that scenario. We do still have to call xe_uc_fw_init() as 
> that's where the FW selection is (and therefore where we find out if 
> it is defined or not), so the solution is to check the enablement 
> status first before checking the return code.
>
Maybe go with this instead?

    Some platforms can have GuC (and HuC?) but not GSC. That would cause
    xe_uc_fw_init(gsc) to return a "not supported" failure code and
    abort all firmware loading. So check for GSC being enabled before
    propagating the failure back up. That way the higher level will keep
    going and load GuC/HuC as appropriate.



>>
>>> +     * To avoid this problem, check the FW status before the return 
>>> code.
>>> +     */
>>> +    ret = xe_uc_fw_init(&gsc->fw);
>>> +    if (!xe_uc_fw_is_enabled(&gsc->fw))
>>> +        return 0;
>>> +    else if (ret)
>>> +        goto out;
>>> +
>>> +    return 0;
>>> +
>>> +out:
>>> +    xe_gt_err(gt, "GSC init failed with %d", ret);
>>> +    return ret;
>>> +}
>>> +
>>> diff --git a/drivers/gpu/drm/xe/xe_gsc.h b/drivers/gpu/drm/xe/xe_gsc.h
>>> new file mode 100644
>>> index 000000000000..baa7f21f4204
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/xe/xe_gsc.h
>>> @@ -0,0 +1,13 @@
>>> +/* SPDX-License-Identifier: MIT */
>>> +/*
>>> + * Copyright © 2023 Intel Corporation
>>> + */
>>> +
>>> +#ifndef _XE_GSC_H_
>>> +#define _XE_GSC_H_
>>> +
>>> +#include "xe_gsc_types.h"
>>> +
>>> +int xe_gsc_init(struct xe_gsc *gsc);
>>> +
>>> +#endif
>>> diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h 
>>> b/drivers/gpu/drm/xe/xe_gsc_types.h
>>> new file mode 100644
>>> index 000000000000..135f156e3736
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/xe/xe_gsc_types.h
>>> @@ -0,0 +1,19 @@
>>> +/* SPDX-License-Identifier: MIT */
>>> +/*
>>> + * Copyright © 2023 Intel Corporation
>>> + */
>>> +
>>> +#ifndef _XE_GSC_TYPES_H_
>>> +#define _XE_GSC_TYPES_H_
>>> +
>>> +#include "xe_uc_fw_types.h"
>>> +
>>> +/**
>>> + * struct xe_gsc - GSC
>>> + */
>>> +struct xe_gsc {
>>> +    /** @fw: Generic uC firmware management */
>>> +    struct xe_uc_fw fw;
>>> +};
>>> +
>>> +#endif
>>> diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
>>> index 784f53c5f282..b67154c78dff 100644
>>> --- a/drivers/gpu/drm/xe/xe_uc.c
>>> +++ b/drivers/gpu/drm/xe/xe_uc.c
>>> @@ -6,6 +6,7 @@
>>>   #include "xe_uc.h"
>>>     #include "xe_device.h"
>>> +#include "xe_gsc.h"
>>>   #include "xe_gt.h"
>>>   #include "xe_guc.h"
>>>   #include "xe_guc_pc.h"
>>> @@ -32,8 +33,8 @@ int xe_uc_init(struct xe_uc *uc)
>>>       int ret;
>>>         /*
>>> -     * We call the GuC/HuC init functions even if GuC submission is 
>>> off to
>>> -     * correctly move our tracking of the FW state to "disabled".
>>> +     * We call the GuC/HuC/GSC init functions even if GuC 
>>> submission is off
>>> +     * to correctly move our tracking of the FW state to "disabled".
>>>        */
>>>         ret = xe_guc_init(&uc->guc);
>>> @@ -44,6 +45,10 @@ int xe_uc_init(struct xe_uc *uc)
>>>       if (ret)
>>>           goto err;
>>>   +    ret = xe_gsc_init(&uc->gsc);
>>> +    if (ret)
>>> +        goto err;
>>> +
>>>       if (!xe_device_uc_enabled(uc_to_xe(uc)))
>>>           return 0;
>>>   diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c 
>>> b/drivers/gpu/drm/xe/xe_uc_fw.c
>>> index 1f7dac394a1d..af3e5cba606f 100644
>>> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
>>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
>>> @@ -158,11 +158,18 @@ XE_HUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
>>>   static struct xe_gt *
>>>   __uc_fw_to_gt(struct xe_uc_fw *uc_fw, enum xe_uc_fw_type type)
>>>   {
>>> -    if (type == XE_UC_FW_TYPE_GUC)
>>> +    XE_WARN_ON(type >= XE_UC_FW_NUM_TYPES);
>>> +
>>> +    switch (type) {
>>> +    case XE_UC_FW_TYPE_GUC:
>>>           return container_of(uc_fw, struct xe_gt, uc.guc.fw);
>>> +    case XE_UC_FW_TYPE_HUC:
>>> +        return container_of(uc_fw, struct xe_gt, uc.huc.fw);
>>> +    case XE_UC_FW_TYPE_GSC:
>>> +        return container_of(uc_fw, struct xe_gt, uc.gsc.fw);
>>> +    }
>>>   -    XE_WARN_ON(type != XE_UC_FW_TYPE_HUC);
>>> -    return container_of(uc_fw, struct xe_gt, uc.huc.fw);
>>> +    return NULL;
>>>   }
>>>     static struct xe_gt *uc_fw_to_gt(struct xe_uc_fw *uc_fw)
>>> @@ -197,6 +204,14 @@ uc_fw_auto_select(struct xe_device *xe, struct 
>>> xe_uc_fw *uc_fw)
>>>       u32 count;
>>>       int i;
>>>   +    /*
>>> +     * GSC FW support is still not fully in place, so we're not 
>>> defining
>>> +     * the FW blob yet because we don't want the driver to attempt 
>>> to load
>>> +     * it until we're ready for it.
>>> +     */
>>> +    if (uc_fw->type == XE_UC_FW_TYPE_GSC)
>>> +        return;
>>> +
>>>       xe_assert(xe, uc_fw->type < ARRAY_SIZE(blobs_all));
>>>       entries = blobs_all[uc_fw->type].entries;
>>>       count = blobs_all[uc_fw->type].count;
>>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.h 
>>> b/drivers/gpu/drm/xe/xe_uc_fw.h
>>> index 1d1a0c156cdf..d4682b0276e2 100644
>>> --- a/drivers/gpu/drm/xe/xe_uc_fw.h
>>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.h
>>> @@ -96,6 +96,8 @@ static inline const char *xe_uc_fw_type_repr(enum 
>>> xe_uc_fw_type type)
>>>           return "GuC";
>>>       case XE_UC_FW_TYPE_HUC:
>>>           return "HuC";
>>> +    case XE_UC_FW_TYPE_GSC:
>>> +        return "GSC";
>>>       }
>>>       return "uC";
>>>   }
>>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw_types.h 
>>> b/drivers/gpu/drm/xe/xe_uc_fw_types.h
>>> index e4774c560e67..239256bfdb07 100644
>>> --- a/drivers/gpu/drm/xe/xe_uc_fw_types.h
>>> +++ b/drivers/gpu/drm/xe/xe_uc_fw_types.h
>>> @@ -55,9 +55,10 @@ enum xe_uc_fw_status {
>>>     enum xe_uc_fw_type {
>>>       XE_UC_FW_TYPE_GUC = 0,
>>> -    XE_UC_FW_TYPE_HUC
>>> +    XE_UC_FW_TYPE_HUC,
>>> +    XE_UC_FW_TYPE_GSC
>>>   };
>>> -#define XE_UC_FW_NUM_TYPES 2
>>> +#define XE_UC_FW_NUM_TYPES 3
>> Why is this not just a sentinel entry of the enum?
>
> No idea, I'm just updating the value. It is the same in i915.
Seems like a good opportunity to fix it.

John.

>
> Daniele
>
>>
>> John.
>>
>>>     /**
>>>    * struct xe_uc_fw_version - Version for XE micro controller firmware
>>> diff --git a/drivers/gpu/drm/xe/xe_uc_types.h 
>>> b/drivers/gpu/drm/xe/xe_uc_types.h
>>> index 49bef6498b85..9924e4484866 100644
>>> --- a/drivers/gpu/drm/xe/xe_uc_types.h
>>> +++ b/drivers/gpu/drm/xe/xe_uc_types.h
>>> @@ -6,6 +6,7 @@
>>>   #ifndef _XE_UC_TYPES_H_
>>>   #define _XE_UC_TYPES_H_
>>>   +#include "xe_gsc_types.h"
>>>   #include "xe_guc_types.h"
>>>   #include "xe_huc_types.h"
>>>   #include "xe_wopcm_types.h"
>>> @@ -18,6 +19,8 @@ struct xe_uc {
>>>       struct xe_guc guc;
>>>       /** @huc: HuC */
>>>       struct xe_huc huc;
>>> +    /** @gsc: Graphics Security Controller */
>>> +    struct xe_gsc gsc;
>>>       /** @wopcm: WOPCM */
>>>       struct xe_wopcm wopcm;
>>>   };
>>
>

[-- Attachment #2: Type: text/html, Size: 20068 bytes --]

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

* Re: [Intel-xe] [PATCH 05/12] drm/xe/gsc: Parse GSC FW header
  2023-11-07 23:45   ` John Harrison
@ 2023-11-07 23:57     ` Daniele Ceraolo Spurio
  2023-11-08  0:42       ` John Harrison
  0 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-07 23:57 UTC (permalink / raw)
  To: John Harrison, intel-xe; +Cc: Lucas De Marchi



On 11/7/2023 3:45 PM, John Harrison wrote:
> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>> The GSC blob starts with a layout header, from which we can move to the
>> boot directory, which in turns allows us to find the CPD. The CPD uses
>> the same format as the one in the HuC binary, so we can re-use the same
>> parsing code to get to the manifest, which contains the release and
>> security versions of the FW.
>>
>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>> Cc: John Harrison <John.C.Harrison@Intel.com>
>> Cc: Lucas De Marchi <lucas.demarchi@intel.com>
>> ---
>>   drivers/gpu/drm/xe/xe_gsc_types.h |   3 +
>>   drivers/gpu/drm/xe/xe_uc_fw.c     |  77 ++++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_uc_fw_abi.h | 113 ++++++++++++++++++++++++++++++
>>   3 files changed, 193 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h 
>> b/drivers/gpu/drm/xe/xe_gsc_types.h
>> index 135f156e3736..1bc50583fe58 100644
>> --- a/drivers/gpu/drm/xe/xe_gsc_types.h
>> +++ b/drivers/gpu/drm/xe/xe_gsc_types.h
>> @@ -14,6 +14,9 @@
>>   struct xe_gsc {
>>       /** @fw: Generic uC firmware management */
>>       struct xe_uc_fw fw;
>> +
>> +    /** @security_version: SVN found in the fetched blob */
>> +    u32 security_version;
> There is no official structure to this version number?

no, it's just a linearly increasing integer, there are no 
minor/patch/build versions involved.

>
>>   };
>>     #endif
>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c 
>> b/drivers/gpu/drm/xe/xe_uc_fw.c
>> index af3e5cba606f..bb38a76eb4a6 100644
>> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
>> @@ -12,6 +12,7 @@
>>   #include "xe_bo.h"
>>   #include "xe_device_types.h"
>>   #include "xe_force_wake.h"
>> +#include "xe_gsc.h"
>>   #include "xe_gt.h"
>>   #include "xe_map.h"
>>   #include "xe_mmio.h"
>> @@ -488,6 +489,13 @@ static int parse_cpd_header(struct xe_uc_fw 
>> *uc_fw, const void *data, size_t siz
>>       release->minor = manifest->fw_version.minor;
>>       release->patch = manifest->fw_version.hotfix;
>>   +    if (uc_fw->type == XE_UC_FW_TYPE_GSC) {
>> +        struct xe_gsc * gsc = container_of(uc_fw, struct xe_gsc, fw);
>> +
>> +        release->build = manifest->fw_version.build;
>> +        gsc->security_version = manifest->security_version;
>> +    }
>> +
>>       /* then optionally look for the css header */
>>       if (css_entry) {
>>           int ret;
>> @@ -517,6 +525,73 @@ static int parse_cpd_header(struct xe_uc_fw 
>> *uc_fw, const void *data, size_t siz
>>       return 0;
>>   }
>>   +static int parse_gsc_layout(struct xe_uc_fw *uc_fw, const void 
>> *data, size_t size)
>> +{
>> +    struct xe_gt *gt = uc_fw_to_gt(uc_fw);
>> +    const struct gsc_layout_pointers *layout = data;
>> +    const struct gsc_bpdt_header *bpdt_header = NULL;
>> +    const struct gsc_bpdt_entry *bpdt_entry = NULL;
>> +    size_t min_size = sizeof(*layout);
>> +    int i;
>> +
>> +    if (size < min_size) {
>> +        xe_gt_err(gt, "GSC FW too small! %zu < %zu\n", size, min_size);
>> +        return -ENODATA;
>> +    }
>> +
>> +    min_size = layout->boot1.offset + layout->boot1.size;
>> +    if (size < min_size) {
>> +        xe_gt_err(gt, "GSC FW too small for boot section! %zu < %zu\n",
>> +              size, min_size);
>> +        return -ENODATA;
>> +    }
>> +
>> +    min_size = sizeof(*bpdt_header);
>> +    if (layout->boot1.size < min_size) {
>> +        xe_gt_err(gt, "GSC FW boot section too small for BPDT 
>> header: %u < %zu\n",
>> +              layout->boot1.size, min_size);
>> +        return -ENODATA;
>> +    }
>> +
>> +    bpdt_header = data + layout->boot1.offset;
>> +    if (bpdt_header->signature != GSC_BPDT_HEADER_SIGNATURE) {
>> +        xe_gt_err(gt, "invalid signature for BPDT header: 0x%08x!\n",
>> +              bpdt_header->signature);
>> +        return -EINVAL;
>> +    }
>> +
>> +    min_size += sizeof(*bpdt_entry) * bpdt_header->descriptor_count;
>> +    if (layout->boot1.size < min_size) {
>> +        xe_gt_err(gt, "GSC FW boot section too small for BPDT 
>> entries: %u < %zu\n",
>> +              layout->boot1.size, min_size);
>> +        return -ENODATA;
>> +    }
>> +
>> +    bpdt_entry = (void *)bpdt_header + sizeof(*bpdt_header);
>> +    for (i = 0; i < bpdt_header->descriptor_count; i++, bpdt_entry++) {
>> +        if ((bpdt_entry->type & GSC_BPDT_ENTRY_TYPE_MASK) !=
>> +            GSC_BPDT_ENTRY_TYPE_GSC_RBE)
>> +            continue;
>> +
>> +        min_size = bpdt_entry->sub_partition_offset;
>> +
>> +        /* the CPD header parser will check that the CPD header fits */
>> +        if (layout->boot1.size < min_size) {
>> +            xe_gt_err(gt, "GSC FW boot section too small for CPD 
>> offset: %u < %zu\n",
>> +                  layout->boot1.size, min_size);
>> +            return -ENODATA;
>> +        }
>> +
>> +        return parse_cpd_header(uc_fw,
>> +                    (void *)bpdt_header + min_size,
>> +                    layout->boot1.size - min_size,
> Could compare this calculation against bpdt_entry->sub_partition_size 
> before bothering to try to decode a partial CPD?

The CPD parser checks for the size. I could add an extra check here and 
bail early, but why add extra case to optimize a scenario that should 
never happen?

>
>> +                    "RBEP.man", NULL);
>> +    }
>> +
>> +    xe_gt_err(gt, "couldn't find CPD header in GSC binary!\n");
>> +    return -ENODATA;
>> +}
>> +
>>   static int parse_headers(struct xe_uc_fw *uc_fw, const struct 
>> firmware *fw)
>>   {
>>       int ret;
>> @@ -526,6 +601,8 @@ static int parse_headers(struct xe_uc_fw *uc_fw, 
>> const struct firmware *fw)
>>        * releases use GSC CPD headers.
>>        */
>>       switch (uc_fw->type) {
>> +    case XE_UC_FW_TYPE_GSC:
>> +        return parse_gsc_layout(uc_fw, fw->data, fw->size);
>>       case XE_UC_FW_TYPE_HUC:
>>           ret = parse_cpd_header(uc_fw, fw->data, fw->size, 
>> "HUCP.man", "huc_fw");
>>           if (!ret || ret != -ENOENT)
>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw_abi.h 
>> b/drivers/gpu/drm/xe/xe_uc_fw_abi.h
>> index d6725c963251..edf2a448f4bb 100644
>> --- a/drivers/gpu/drm/xe/xe_uc_fw_abi.h
>> +++ b/drivers/gpu/drm/xe/xe_uc_fw_abi.h
>> @@ -140,6 +140,58 @@ static_assert(sizeof(struct uc_css_header) == 128);
>>    *    |      RSA Key (MTL+ only)                       |
>>    *    |      ...                                       |
>>    *    +================================================+
>> + *
>> + * The GSC binary starts instead with a layout header, which 
>> contains the
>> + * locations of the various partitions of the binary. The one we're 
>> interested
>> + * in is the boot1 partition, where we can find a BPDT header 
>> followed by
>> + * entries, one of which points to the RBE sub-section of the 
>> partition, which
>> + * contains the CPD. The GSC blob does not contain a CSS-based 
>> binary, so we
>> + * only need to look for the manifest, which is under the "RBEP.man" 
>> CPD entry.
>> + * Note that we have no need to find where the actual FW code is 
>> inside the
>> + * image because the GSC ROM will itself parse the headers to find 
>> it and load
>> + * it.
>> + * The GSC firmware header layout looks like this::
>> + *
>> + *    +================================================+
>> + *    |  Layout Pointers                               |
>> + *    |      ...                                       |
>> + *    |      Boot1 offset >---------------------------|------o
>> + *    |      ...                                       |      |
>> + *    +================================================+      |
>> + *                                                            |
>> + *    +================================================+      |
>> + *    |  BPDT header |<-----o
>> + *    +================================================+
>> + *    |  BPDT entries[]                                |
>> + *    |      entry1                                    |
>> + *    |      ...                                       |
>> + *    |      entryX                                    |
>> + *    |          type == GSC_RBE                       |
>> + *    |          offset >-----------------------------|------o
>> + *    |      ...                                       |      |
>> + *    +================================================+      |
>> + *                                                            |
>> + *    +================================================+      |
>> + *    |  CPD Header |<-----o
>> + *    +================================================+
>> + *    |  CPD entries[]                                 |
>> + *    |      entry1                                    |
>> + *    |      ...                                       |
>> + *    |      entryX                                    |
>> + *    |          "RBEP.man"                            |
>> + *    |           ...                                  |
>> + *    |           offset >----------------------------|------o
>> + *    |      ...                                       |      |
>> + *    +================================================+      |
>> + *                                                            |
>> + *    +================================================+      |
>> + *    | Manifest Header |<-----o
>> + *    |  ...                                           |
>> + *    |  FW version                                    |
>> + *    |  ...                                           |
>> + *    |  Security version                              |
>> + *    |  ...                                           |
>> + *    +================================================+
>>    */
>>     struct gsc_version {
>> @@ -149,6 +201,67 @@ struct gsc_version {
>>       u16 build;
>>   } __packed;
>>   +struct gsc_partition {
>> +    u32 offset;
>> +    u32 size;
>> +} __packed;
>> +
>> +struct gsc_layout_pointers {
>> +    u8 rom_bypass_vector[16];
>> +
>> +    /* size of pointers layout not including ROM bypass vector */
> pointers layout -> layout pointers?

I'll just simplify it to "size of this header section"

>
>> +    u16 size;
>> +
>> +    /*
>> +     * bit0: Backup copy of layout pointers exist
> exist -> exists

ack

>
>> +     * bits1-15: reserved
>> +     */
>> +    u8 flags;
>> +
>> +    u8 reserved;
>> +
>> +    u32 crc32;
> Should we be doing anything to test against this crc or the one in the 
> bpdt_header below?

No, the GSC ROM checks those at load time.

Daniele

>
> John.
>
>> +
>> +    struct gsc_partition datap;
>> +    struct gsc_partition boot1;
>> +    struct gsc_partition boot2;
>> +    struct gsc_partition boot3;
>> +    struct gsc_partition boot4;
>> +    struct gsc_partition boot5;
>> +    struct gsc_partition temp_pages;
>> +} __packed;
>> +
>> +/* Boot partition structures */
>> +struct gsc_bpdt_header {
>> +    u32 signature;
>> +#define GSC_BPDT_HEADER_SIGNATURE 0x000055AA
>> +
>> +    u16 descriptor_count; /* num of entries after the header */
>> +
>> +    u8 version;
>> +    u8 configuration;
>> +
>> +    u32 crc32;
>> +
>> +    u32 build_version;
>> +    struct gsc_version tool_version;
>> +} __packed;
>> +
>> +struct gsc_bpdt_entry {
>> +    /*
>> +     * Bits 0-15: BPDT entry type
>> +     * Bits 16-17: reserved
>> +     * Bit 18: code sub-partition
>> +     * Bits 19-31: reserved
>> +     */
>> +    u32 type;
>> +#define GSC_BPDT_ENTRY_TYPE_MASK GENMASK(15, 0)
>> +#define GSC_BPDT_ENTRY_TYPE_GSC_RBE 0x1
>> +
>> +    u32 sub_partition_offset; /* from the base of the BPDT header */
>> +    u32 sub_partition_size;
>> +} __packed;
>> +
>>   /* Code partition directory (CPD) structures */
>>   struct gsc_cpd_header_v2 {
>>       u32 header_marker;
>


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

* Re: [Intel-xe] [PATCH 04/12] drm/xe/gsc: Introduce GSC FW
  2023-11-07 23:52       ` John Harrison
@ 2023-11-07 23:59         ` Daniele Ceraolo Spurio
  0 siblings, 0 replies; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-07 23:59 UTC (permalink / raw)
  To: John Harrison, intel-xe

[-- Attachment #1: Type: text/plain, Size: 11314 bytes --]



On 11/7/2023 3:52 PM, John Harrison wrote:
> On 11/7/2023 15:32, Daniele Ceraolo Spurio wrote:
>> On 11/7/2023 3:26 PM, John Harrison wrote:
>>> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>>>> Add the basic definitions and init function. Same as HuC, GSC is only
>>>> supported on the media GT on MTL and newer platforms.
>>>> Note that the GSC requires submission resources which can't be 
>>>> allocated
>>>> during init (because we don't have the hwconfig yet), so it can't be
>>>> marked as loadable at the end of the init function. The allocation of
>>>> those resources will come in the patch that makes use of them to load
>>>> the FW.
>>>>
>>>> Signed-off-by: Daniele Ceraolo Spurio 
>>>> <daniele.ceraolospurio@intel.com>
>>>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>>>> Cc: John Harrison <John.C.Harrison@Intel.com>
>>>> ---
>>>>   drivers/gpu/drm/xe/Makefile         |  1 +
>>>>   drivers/gpu/drm/xe/xe_gsc.c         | 50 
>>>> +++++++++++++++++++++++++++++
>>>>   drivers/gpu/drm/xe/xe_gsc.h         | 13 ++++++++
>>>>   drivers/gpu/drm/xe/xe_gsc_types.h   | 19 +++++++++++
>>>>   drivers/gpu/drm/xe/xe_uc.c          |  9 ++++--
>>>>   drivers/gpu/drm/xe/xe_uc_fw.c       | 21 ++++++++++--
>>>>   drivers/gpu/drm/xe/xe_uc_fw.h       |  2 ++
>>>>   drivers/gpu/drm/xe/xe_uc_fw_types.h |  5 +--
>>>>   drivers/gpu/drm/xe/xe_uc_types.h    |  3 ++
>>>>   9 files changed, 116 insertions(+), 7 deletions(-)
>>>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc.c
>>>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc.h
>>>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_types.h
>>>>
>>>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
>>>> index cee57681732d..474b6044d054 100644
>>>> --- a/drivers/gpu/drm/xe/Makefile
>>>> +++ b/drivers/gpu/drm/xe/Makefile
>>>> @@ -57,6 +57,7 @@ xe-y += xe_bb.o \
>>>>       xe_exec_queue.o \
>>>>       xe_force_wake.o \
>>>>       xe_ggtt.o \
>>>> +    xe_gsc.o \
>>>>       xe_gt.o \
>>>>       xe_gt_clock.o \
>>>>       xe_gt_debugfs.o \
>>>> diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
>>>> new file mode 100644
>>>> index 000000000000..3f709577d73b
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/xe/xe_gsc.c
>>>> @@ -0,0 +1,50 @@
>>>> +// SPDX-License-Identifier: MIT
>>>> +/*
>>>> + * Copyright © 2023 Intel Corporation
>>>> + */
>>>> +
>>>> +#include "xe_gsc.h"
>>>> +
>>>> +#include "xe_device.h"
>>>> +#include "xe_gt.h"
>>>> +#include "xe_gt_printk.h"
>>>> +#include "xe_uc_fw.h"
>>>> +
>>>> +static struct xe_gt *
>>>> +gsc_to_gt(struct xe_gsc *gsc)
>>>> +{
>>>> +    return container_of(gsc, struct xe_gt, uc.gsc);
>>>> +}
>>>> +
>>>> +int xe_gsc_init(struct xe_gsc *gsc)
>>>> +{
>>>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>>>> +    struct xe_tile *tile = gt_to_tile(gt);
>>>> +    int ret;
>>>> +
>>>> +    gsc->fw.type = XE_UC_FW_TYPE_GSC;
>>>> +
>>>> +    /* The GSC uC is only available on the media GT */
>>>> +    if (tile->media_gt && (gt != tile->media_gt)) {
>>>> +        xe_uc_fw_change_status(&gsc->fw, 
>>>> XE_UC_FIRMWARE_NOT_SUPPORTED);
>>>> +        return 0;
>>>> +    }
>>>> +
>>>> +    /*
>>>> +     * GSC can be "not supported" where GuC is instead supported, 
>>>> so we
>>>> +     * don't want to fail if xe_uc_fw_init() returns an error due 
>>>> to that.
>>> Not following this comment. Can you explain more?
>>
>> xe_uc_fw_init() is going to fail if the GSC FW is not defined for the 
>> platform. The uC switch is global for all FWs, so either all FW init 
>> functions are called or none of them; since we do have to handle the 
>> case where GuC is supported and GSC is not, xe_gsc_init() needs to 
>> not fail in that scenario. We do still have to call xe_uc_fw_init() 
>> as that's where the FW selection is (and therefore where we find out 
>> if it is defined or not), so the solution is to check the enablement 
>> status first before checking the return code.
>>
> Maybe go with this instead?
>
>     Some platforms can have GuC (and HuC?) but not GSC. That would
>     cause xe_uc_fw_init(gsc) to return a "not supported" failure code
>     and abort all firmware loading. So check for GSC being enabled
>     before propagating the failure back up. That way the higher level
>     will keep going and load GuC/HuC as appropriate.
>

HuC can also be "not supported", but apart from that I'll switch to the 
comment you suggested.

Daniele

>
>
>>>
>>>> +     * To avoid this problem, check the FW status before the 
>>>> return code.
>>>> +     */
>>>> +    ret = xe_uc_fw_init(&gsc->fw);
>>>> +    if (!xe_uc_fw_is_enabled(&gsc->fw))
>>>> +        return 0;
>>>> +    else if (ret)
>>>> +        goto out;
>>>> +
>>>> +    return 0;
>>>> +
>>>> +out:
>>>> +    xe_gt_err(gt, "GSC init failed with %d", ret);
>>>> +    return ret;
>>>> +}
>>>> +
>>>> diff --git a/drivers/gpu/drm/xe/xe_gsc.h b/drivers/gpu/drm/xe/xe_gsc.h
>>>> new file mode 100644
>>>> index 000000000000..baa7f21f4204
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/xe/xe_gsc.h
>>>> @@ -0,0 +1,13 @@
>>>> +/* SPDX-License-Identifier: MIT */
>>>> +/*
>>>> + * Copyright © 2023 Intel Corporation
>>>> + */
>>>> +
>>>> +#ifndef _XE_GSC_H_
>>>> +#define _XE_GSC_H_
>>>> +
>>>> +#include "xe_gsc_types.h"
>>>> +
>>>> +int xe_gsc_init(struct xe_gsc *gsc);
>>>> +
>>>> +#endif
>>>> diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h 
>>>> b/drivers/gpu/drm/xe/xe_gsc_types.h
>>>> new file mode 100644
>>>> index 000000000000..135f156e3736
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/xe/xe_gsc_types.h
>>>> @@ -0,0 +1,19 @@
>>>> +/* SPDX-License-Identifier: MIT */
>>>> +/*
>>>> + * Copyright © 2023 Intel Corporation
>>>> + */
>>>> +
>>>> +#ifndef _XE_GSC_TYPES_H_
>>>> +#define _XE_GSC_TYPES_H_
>>>> +
>>>> +#include "xe_uc_fw_types.h"
>>>> +
>>>> +/**
>>>> + * struct xe_gsc - GSC
>>>> + */
>>>> +struct xe_gsc {
>>>> +    /** @fw: Generic uC firmware management */
>>>> +    struct xe_uc_fw fw;
>>>> +};
>>>> +
>>>> +#endif
>>>> diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
>>>> index 784f53c5f282..b67154c78dff 100644
>>>> --- a/drivers/gpu/drm/xe/xe_uc.c
>>>> +++ b/drivers/gpu/drm/xe/xe_uc.c
>>>> @@ -6,6 +6,7 @@
>>>>   #include "xe_uc.h"
>>>>     #include "xe_device.h"
>>>> +#include "xe_gsc.h"
>>>>   #include "xe_gt.h"
>>>>   #include "xe_guc.h"
>>>>   #include "xe_guc_pc.h"
>>>> @@ -32,8 +33,8 @@ int xe_uc_init(struct xe_uc *uc)
>>>>       int ret;
>>>>         /*
>>>> -     * We call the GuC/HuC init functions even if GuC submission 
>>>> is off to
>>>> -     * correctly move our tracking of the FW state to "disabled".
>>>> +     * We call the GuC/HuC/GSC init functions even if GuC 
>>>> submission is off
>>>> +     * to correctly move our tracking of the FW state to "disabled".
>>>>        */
>>>>         ret = xe_guc_init(&uc->guc);
>>>> @@ -44,6 +45,10 @@ int xe_uc_init(struct xe_uc *uc)
>>>>       if (ret)
>>>>           goto err;
>>>>   +    ret = xe_gsc_init(&uc->gsc);
>>>> +    if (ret)
>>>> +        goto err;
>>>> +
>>>>       if (!xe_device_uc_enabled(uc_to_xe(uc)))
>>>>           return 0;
>>>>   diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c 
>>>> b/drivers/gpu/drm/xe/xe_uc_fw.c
>>>> index 1f7dac394a1d..af3e5cba606f 100644
>>>> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
>>>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
>>>> @@ -158,11 +158,18 @@ XE_HUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
>>>>   static struct xe_gt *
>>>>   __uc_fw_to_gt(struct xe_uc_fw *uc_fw, enum xe_uc_fw_type type)
>>>>   {
>>>> -    if (type == XE_UC_FW_TYPE_GUC)
>>>> +    XE_WARN_ON(type >= XE_UC_FW_NUM_TYPES);
>>>> +
>>>> +    switch (type) {
>>>> +    case XE_UC_FW_TYPE_GUC:
>>>>           return container_of(uc_fw, struct xe_gt, uc.guc.fw);
>>>> +    case XE_UC_FW_TYPE_HUC:
>>>> +        return container_of(uc_fw, struct xe_gt, uc.huc.fw);
>>>> +    case XE_UC_FW_TYPE_GSC:
>>>> +        return container_of(uc_fw, struct xe_gt, uc.gsc.fw);
>>>> +    }
>>>>   -    XE_WARN_ON(type != XE_UC_FW_TYPE_HUC);
>>>> -    return container_of(uc_fw, struct xe_gt, uc.huc.fw);
>>>> +    return NULL;
>>>>   }
>>>>     static struct xe_gt *uc_fw_to_gt(struct xe_uc_fw *uc_fw)
>>>> @@ -197,6 +204,14 @@ uc_fw_auto_select(struct xe_device *xe, struct 
>>>> xe_uc_fw *uc_fw)
>>>>       u32 count;
>>>>       int i;
>>>>   +    /*
>>>> +     * GSC FW support is still not fully in place, so we're not 
>>>> defining
>>>> +     * the FW blob yet because we don't want the driver to attempt 
>>>> to load
>>>> +     * it until we're ready for it.
>>>> +     */
>>>> +    if (uc_fw->type == XE_UC_FW_TYPE_GSC)
>>>> +        return;
>>>> +
>>>>       xe_assert(xe, uc_fw->type < ARRAY_SIZE(blobs_all));
>>>>       entries = blobs_all[uc_fw->type].entries;
>>>>       count = blobs_all[uc_fw->type].count;
>>>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.h 
>>>> b/drivers/gpu/drm/xe/xe_uc_fw.h
>>>> index 1d1a0c156cdf..d4682b0276e2 100644
>>>> --- a/drivers/gpu/drm/xe/xe_uc_fw.h
>>>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.h
>>>> @@ -96,6 +96,8 @@ static inline const char *xe_uc_fw_type_repr(enum 
>>>> xe_uc_fw_type type)
>>>>           return "GuC";
>>>>       case XE_UC_FW_TYPE_HUC:
>>>>           return "HuC";
>>>> +    case XE_UC_FW_TYPE_GSC:
>>>> +        return "GSC";
>>>>       }
>>>>       return "uC";
>>>>   }
>>>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw_types.h 
>>>> b/drivers/gpu/drm/xe/xe_uc_fw_types.h
>>>> index e4774c560e67..239256bfdb07 100644
>>>> --- a/drivers/gpu/drm/xe/xe_uc_fw_types.h
>>>> +++ b/drivers/gpu/drm/xe/xe_uc_fw_types.h
>>>> @@ -55,9 +55,10 @@ enum xe_uc_fw_status {
>>>>     enum xe_uc_fw_type {
>>>>       XE_UC_FW_TYPE_GUC = 0,
>>>> -    XE_UC_FW_TYPE_HUC
>>>> +    XE_UC_FW_TYPE_HUC,
>>>> +    XE_UC_FW_TYPE_GSC
>>>>   };
>>>> -#define XE_UC_FW_NUM_TYPES 2
>>>> +#define XE_UC_FW_NUM_TYPES 3
>>> Why is this not just a sentinel entry of the enum?
>>
>> No idea, I'm just updating the value. It is the same in i915.
> Seems like a good opportunity to fix it.
>
> John.
>
>>
>> Daniele
>>
>>>
>>> John.
>>>
>>>>     /**
>>>>    * struct xe_uc_fw_version - Version for XE micro controller 
>>>> firmware
>>>> diff --git a/drivers/gpu/drm/xe/xe_uc_types.h 
>>>> b/drivers/gpu/drm/xe/xe_uc_types.h
>>>> index 49bef6498b85..9924e4484866 100644
>>>> --- a/drivers/gpu/drm/xe/xe_uc_types.h
>>>> +++ b/drivers/gpu/drm/xe/xe_uc_types.h
>>>> @@ -6,6 +6,7 @@
>>>>   #ifndef _XE_UC_TYPES_H_
>>>>   #define _XE_UC_TYPES_H_
>>>>   +#include "xe_gsc_types.h"
>>>>   #include "xe_guc_types.h"
>>>>   #include "xe_huc_types.h"
>>>>   #include "xe_wopcm_types.h"
>>>> @@ -18,6 +19,8 @@ struct xe_uc {
>>>>       struct xe_guc guc;
>>>>       /** @huc: HuC */
>>>>       struct xe_huc huc;
>>>> +    /** @gsc: Graphics Security Controller */
>>>> +    struct xe_gsc gsc;
>>>>       /** @wopcm: WOPCM */
>>>>       struct xe_wopcm wopcm;
>>>>   };
>>>
>>
>

[-- Attachment #2: Type: text/html, Size: 18841 bytes --]

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

* Re: [Intel-xe] [PATCH 05/12] drm/xe/gsc: Parse GSC FW header
  2023-11-07 23:57     ` Daniele Ceraolo Spurio
@ 2023-11-08  0:42       ` John Harrison
  0 siblings, 0 replies; 56+ messages in thread
From: John Harrison @ 2023-11-08  0:42 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe; +Cc: Lucas De Marchi

On 11/7/2023 15:57, Daniele Ceraolo Spurio wrote:
> On 11/7/2023 3:45 PM, John Harrison wrote:
>> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>>> The GSC blob starts with a layout header, from which we can move to the
>>> boot directory, which in turns allows us to find the CPD. The CPD uses
>>> the same format as the one in the HuC binary, so we can re-use the same
>>> parsing code to get to the manifest, which contains the release and
>>> security versions of the FW.
>>>
>>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>>> Cc: John Harrison <John.C.Harrison@Intel.com>
>>> Cc: Lucas De Marchi <lucas.demarchi@intel.com>
>>> ---
>>>   drivers/gpu/drm/xe/xe_gsc_types.h |   3 +
>>>   drivers/gpu/drm/xe/xe_uc_fw.c     |  77 ++++++++++++++++++++
>>>   drivers/gpu/drm/xe/xe_uc_fw_abi.h | 113 
>>> ++++++++++++++++++++++++++++++
>>>   3 files changed, 193 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h 
>>> b/drivers/gpu/drm/xe/xe_gsc_types.h
>>> index 135f156e3736..1bc50583fe58 100644
>>> --- a/drivers/gpu/drm/xe/xe_gsc_types.h
>>> +++ b/drivers/gpu/drm/xe/xe_gsc_types.h
>>> @@ -14,6 +14,9 @@
>>>   struct xe_gsc {
>>>       /** @fw: Generic uC firmware management */
>>>       struct xe_uc_fw fw;
>>> +
>>> +    /** @security_version: SVN found in the fetched blob */
>>> +    u32 security_version;
>> There is no official structure to this version number?
>
> no, it's just a linearly increasing integer, there are no 
> minor/patch/build versions involved.
>
>>
>>>   };
>>>     #endif
>>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c 
>>> b/drivers/gpu/drm/xe/xe_uc_fw.c
>>> index af3e5cba606f..bb38a76eb4a6 100644
>>> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
>>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
>>> @@ -12,6 +12,7 @@
>>>   #include "xe_bo.h"
>>>   #include "xe_device_types.h"
>>>   #include "xe_force_wake.h"
>>> +#include "xe_gsc.h"
>>>   #include "xe_gt.h"
>>>   #include "xe_map.h"
>>>   #include "xe_mmio.h"
>>> @@ -488,6 +489,13 @@ static int parse_cpd_header(struct xe_uc_fw 
>>> *uc_fw, const void *data, size_t siz
>>>       release->minor = manifest->fw_version.minor;
>>>       release->patch = manifest->fw_version.hotfix;
>>>   +    if (uc_fw->type == XE_UC_FW_TYPE_GSC) {
>>> +        struct xe_gsc * gsc = container_of(uc_fw, struct xe_gsc, fw);
>>> +
>>> +        release->build = manifest->fw_version.build;
>>> +        gsc->security_version = manifest->security_version;
>>> +    }
>>> +
>>>       /* then optionally look for the css header */
>>>       if (css_entry) {
>>>           int ret;
>>> @@ -517,6 +525,73 @@ static int parse_cpd_header(struct xe_uc_fw 
>>> *uc_fw, const void *data, size_t siz
>>>       return 0;
>>>   }
>>>   +static int parse_gsc_layout(struct xe_uc_fw *uc_fw, const void 
>>> *data, size_t size)
>>> +{
>>> +    struct xe_gt *gt = uc_fw_to_gt(uc_fw);
>>> +    const struct gsc_layout_pointers *layout = data;
>>> +    const struct gsc_bpdt_header *bpdt_header = NULL;
>>> +    const struct gsc_bpdt_entry *bpdt_entry = NULL;
>>> +    size_t min_size = sizeof(*layout);
>>> +    int i;
>>> +
>>> +    if (size < min_size) {
>>> +        xe_gt_err(gt, "GSC FW too small! %zu < %zu\n", size, 
>>> min_size);
>>> +        return -ENODATA;
>>> +    }
>>> +
>>> +    min_size = layout->boot1.offset + layout->boot1.size;
>>> +    if (size < min_size) {
>>> +        xe_gt_err(gt, "GSC FW too small for boot section! %zu < 
>>> %zu\n",
>>> +              size, min_size);
>>> +        return -ENODATA;
>>> +    }
>>> +
>>> +    min_size = sizeof(*bpdt_header);
>>> +    if (layout->boot1.size < min_size) {
>>> +        xe_gt_err(gt, "GSC FW boot section too small for BPDT 
>>> header: %u < %zu\n",
>>> +              layout->boot1.size, min_size);
>>> +        return -ENODATA;
>>> +    }
>>> +
>>> +    bpdt_header = data + layout->boot1.offset;
>>> +    if (bpdt_header->signature != GSC_BPDT_HEADER_SIGNATURE) {
>>> +        xe_gt_err(gt, "invalid signature for BPDT header: 0x%08x!\n",
>>> +              bpdt_header->signature);
>>> +        return -EINVAL;
>>> +    }
>>> +
>>> +    min_size += sizeof(*bpdt_entry) * bpdt_header->descriptor_count;
>>> +    if (layout->boot1.size < min_size) {
>>> +        xe_gt_err(gt, "GSC FW boot section too small for BPDT 
>>> entries: %u < %zu\n",
>>> +              layout->boot1.size, min_size);
>>> +        return -ENODATA;
>>> +    }
>>> +
>>> +    bpdt_entry = (void *)bpdt_header + sizeof(*bpdt_header);
>>> +    for (i = 0; i < bpdt_header->descriptor_count; i++, 
>>> bpdt_entry++) {
>>> +        if ((bpdt_entry->type & GSC_BPDT_ENTRY_TYPE_MASK) !=
>>> +            GSC_BPDT_ENTRY_TYPE_GSC_RBE)
>>> +            continue;
>>> +
>>> +        min_size = bpdt_entry->sub_partition_offset;
>>> +
>>> +        /* the CPD header parser will check that the CPD header 
>>> fits */
>>> +        if (layout->boot1.size < min_size) {
>>> +            xe_gt_err(gt, "GSC FW boot section too small for CPD 
>>> offset: %u < %zu\n",
>>> +                  layout->boot1.size, min_size);
>>> +            return -ENODATA;
>>> +        }
>>> +
>>> +        return parse_cpd_header(uc_fw,
>>> +                    (void *)bpdt_header + min_size,
>>> +                    layout->boot1.size - min_size,
>> Could compare this calculation against bpdt_entry->sub_partition_size 
>> before bothering to try to decode a partial CPD?
>
> The CPD parser checks for the size. I could add an extra check here 
> and bail early, but why add extra case to optimize a scenario that 
> should never happen?
Fair enough.

>
>>
>>> +                    "RBEP.man", NULL);
>>> +    }
>>> +
>>> +    xe_gt_err(gt, "couldn't find CPD header in GSC binary!\n");
>>> +    return -ENODATA;
>>> +}
>>> +
>>>   static int parse_headers(struct xe_uc_fw *uc_fw, const struct 
>>> firmware *fw)
>>>   {
>>>       int ret;
>>> @@ -526,6 +601,8 @@ static int parse_headers(struct xe_uc_fw *uc_fw, 
>>> const struct firmware *fw)
>>>        * releases use GSC CPD headers.
>>>        */
>>>       switch (uc_fw->type) {
>>> +    case XE_UC_FW_TYPE_GSC:
>>> +        return parse_gsc_layout(uc_fw, fw->data, fw->size);
>>>       case XE_UC_FW_TYPE_HUC:
>>>           ret = parse_cpd_header(uc_fw, fw->data, fw->size, 
>>> "HUCP.man", "huc_fw");
>>>           if (!ret || ret != -ENOENT)
>>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw_abi.h 
>>> b/drivers/gpu/drm/xe/xe_uc_fw_abi.h
>>> index d6725c963251..edf2a448f4bb 100644
>>> --- a/drivers/gpu/drm/xe/xe_uc_fw_abi.h
>>> +++ b/drivers/gpu/drm/xe/xe_uc_fw_abi.h
>>> @@ -140,6 +140,58 @@ static_assert(sizeof(struct uc_css_header) == 
>>> 128);
>>>    *    |      RSA Key (MTL+ only)                       |
>>>    *    |      ...                                       |
>>>    *    +================================================+
>>> + *
>>> + * The GSC binary starts instead with a layout header, which 
>>> contains the
>>> + * locations of the various partitions of the binary. The one we're 
>>> interested
>>> + * in is the boot1 partition, where we can find a BPDT header 
>>> followed by
>>> + * entries, one of which points to the RBE sub-section of the 
>>> partition, which
>>> + * contains the CPD. The GSC blob does not contain a CSS-based 
>>> binary, so we
>>> + * only need to look for the manifest, which is under the 
>>> "RBEP.man" CPD entry.
>>> + * Note that we have no need to find where the actual FW code is 
>>> inside the
>>> + * image because the GSC ROM will itself parse the headers to find 
>>> it and load
>>> + * it.
>>> + * The GSC firmware header layout looks like this::
>>> + *
>>> + *    +================================================+
>>> + *    |  Layout Pointers                               |
>>> + *    |      ...                                       |
>>> + *    |      Boot1 offset >---------------------------|------o
>>> + *    |      ...                                       | |
>>> + *    +================================================+ |
>>> + * |
>>> + *    +================================================+ |
>>> + *    |  BPDT header |<-----o
>>> + *    +================================================+
>>> + *    |  BPDT entries[]                                |
>>> + *    |      entry1                                    |
>>> + *    |      ...                                       |
>>> + *    |      entryX                                    |
>>> + *    |          type == GSC_RBE                       |
>>> + *    |          offset >-----------------------------|------o
>>> + *    |      ...                                       | |
>>> + *    +================================================+ |
>>> + * |
>>> + *    +================================================+ |
>>> + *    |  CPD Header |<-----o
>>> + *    +================================================+
>>> + *    |  CPD entries[]                                 |
>>> + *    |      entry1                                    |
>>> + *    |      ...                                       |
>>> + *    |      entryX                                    |
>>> + *    |          "RBEP.man"                            |
>>> + *    |           ...                                  |
>>> + *    |           offset >----------------------------|------o
>>> + *    |      ...                                       | |
>>> + *    +================================================+ |
>>> + * |
>>> + *    +================================================+ |
>>> + *    | Manifest Header |<-----o
>>> + *    |  ...                                           |
>>> + *    |  FW version                                    |
>>> + *    |  ...                                           |
>>> + *    |  Security version                              |
>>> + *    |  ...                                           |
>>> + *    +================================================+
>>>    */
>>>     struct gsc_version {
>>> @@ -149,6 +201,67 @@ struct gsc_version {
>>>       u16 build;
>>>   } __packed;
>>>   +struct gsc_partition {
>>> +    u32 offset;
>>> +    u32 size;
>>> +} __packed;
>>> +
>>> +struct gsc_layout_pointers {
>>> +    u8 rom_bypass_vector[16];
>>> +
>>> +    /* size of pointers layout not including ROM bypass vector */
>> pointers layout -> layout pointers?
>
> I'll just simplify it to "size of this header section"
>
>>
>>> +    u16 size;
>>> +
>>> +    /*
>>> +     * bit0: Backup copy of layout pointers exist
>> exist -> exists
>
> ack
>
>>
>>> +     * bits1-15: reserved
>>> +     */
>>> +    u8 flags;
>>> +
>>> +    u8 reserved;
>>> +
>>> +    u32 crc32;
>> Should we be doing anything to test against this crc or the one in 
>> the bpdt_header below?
>
> No, the GSC ROM checks those at load time.
Okay.

John.

>
> Daniele
>
>>
>> John.
>>
>>> +
>>> +    struct gsc_partition datap;
>>> +    struct gsc_partition boot1;
>>> +    struct gsc_partition boot2;
>>> +    struct gsc_partition boot3;
>>> +    struct gsc_partition boot4;
>>> +    struct gsc_partition boot5;
>>> +    struct gsc_partition temp_pages;
>>> +} __packed;
>>> +
>>> +/* Boot partition structures */
>>> +struct gsc_bpdt_header {
>>> +    u32 signature;
>>> +#define GSC_BPDT_HEADER_SIGNATURE 0x000055AA
>>> +
>>> +    u16 descriptor_count; /* num of entries after the header */
>>> +
>>> +    u8 version;
>>> +    u8 configuration;
>>> +
>>> +    u32 crc32;
>>> +
>>> +    u32 build_version;
>>> +    struct gsc_version tool_version;
>>> +} __packed;
>>> +
>>> +struct gsc_bpdt_entry {
>>> +    /*
>>> +     * Bits 0-15: BPDT entry type
>>> +     * Bits 16-17: reserved
>>> +     * Bit 18: code sub-partition
>>> +     * Bits 19-31: reserved
>>> +     */
>>> +    u32 type;
>>> +#define GSC_BPDT_ENTRY_TYPE_MASK GENMASK(15, 0)
>>> +#define GSC_BPDT_ENTRY_TYPE_GSC_RBE 0x1
>>> +
>>> +    u32 sub_partition_offset; /* from the base of the BPDT header */
>>> +    u32 sub_partition_size;
>>> +} __packed;
>>> +
>>>   /* Code partition directory (CPD) structures */
>>>   struct gsc_cpd_header_v2 {
>>>       u32 header_marker;
>>
>


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

* Re: [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions
  2023-10-31 19:29     ` Daniele Ceraolo Spurio
@ 2023-11-08  8:25       ` Kandpal, Suraj
  0 siblings, 0 replies; 56+ messages in thread
From: Kandpal, Suraj @ 2023-11-08  8:25 UTC (permalink / raw)
  To: Ceraolo Spurio, Daniele, intel-xe@lists.freedesktop.org

[-- Attachment #1: Type: text/plain, Size: 15761 bytes --]



On 10/31/2023 1:08 AM, Kandpal, Suraj wrote:





-----Original Message-----

From: Ceraolo Spurio, Daniele <daniele.ceraolospurio@intel.com><mailto:daniele.ceraolospurio@intel.com>

Sent: Saturday, October 28, 2023 3:59 AM

To: intel-xe@lists.freedesktop.org<mailto:intel-xe@lists.freedesktop.org>

Cc: Ceraolo Spurio, Daniele <daniele.ceraolospurio@intel.com><mailto:daniele.ceraolospurio@intel.com>; Teres Alexis,

Alan Previn <alan.previn.teres.alexis@intel.com><mailto:alan.previn.teres.alexis@intel.com>; Kandpal, Suraj

<suraj.kandpal@intel.com><mailto:suraj.kandpal@intel.com>

Subject: [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet

submissions



Communication with the GSC FW is done via input/output buffers, whose

addresses are provided via a GSCCS command. The buffers contain a generic

header and a client-specific packet (e.g. PXP, HDCP); the clients don't care

about the header format and/or the GSCCS command in the batch, they only

care about their client-specific header. This patch therefore introduces helpers

that allow the callers to automatically fill in the input header, submit the GSCCS

job and decode the output header, to make it so that the caller only needs to

worry about their client-specific input and output messages.



NOTE: this patch by itself only adds the interface so it does nothing, I've kept it

separate for review but the plan is to squash it with the follow up patch before

merge, so that the interface and the user are introduced at the same time.



Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com><mailto:daniele.ceraolospurio@intel.com>

Cc: Alan Previn <alan.previn.teres.alexis@intel.com><mailto:alan.previn.teres.alexis@intel.com>

Cc: Suraj Kandpal <suraj.kandpal@intel.com><mailto:suraj.kandpal@intel.com>

---

 drivers/gpu/drm/xe/Makefile                   |   1 +

 .../gpu/drm/xe/abi/gsc_command_header_abi.h   |  46 +++++

 .../gpu/drm/xe/instructions/xe_gsc_commands.h |   2 +

 drivers/gpu/drm/xe/xe_gsc_submit.c            | 170 ++++++++++++++++++

 drivers/gpu/drm/xe/xe_gsc_submit.h            |  30 ++++

 5 files changed, 249 insertions(+)

 create mode 100644 drivers/gpu/drm/xe/abi/gsc_command_header_abi.h

 create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.c

 create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.h



diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index

4a442dcf4d79..876c122ad63c 100644

--- a/drivers/gpu/drm/xe/Makefile

+++ b/drivers/gpu/drm/xe/Makefile

@@ -58,6 +58,7 @@ xe-y += xe_bb.o \

  xe_force_wake.o \

  xe_ggtt.o \

  xe_gsc.o \

+ xe_gsc_submit.o \

  xe_gt.o \

  xe_gt_clock.o \

  xe_gt_debugfs.o \

diff --git a/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h

b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h

new file mode 100644

index 000000000000..a4c2646803b5

--- /dev/null

+++ b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h

@@ -0,0 +1,46 @@

+/* SPDX-License-Identifier: MIT */

+/*

+ * Copyright © 2023 Intel Corporation

+ */

+

+#ifndef _ABI_GSC_COMMAND_HEADER_ABI_H

+#define _ABI_GSC_COMMAND_HEADER_ABI_H

+

+#include <linux/types.h>

+

+struct intel_gsc_mtl_header {

+ u32 validity_marker;

+#define GSC_HECI_VALIDITY_MARKER 0xA578875A

+

+ u8 heci_client_id;



Also during adding this is i915 we had decided to add certain defines

As seen here below may be add them as well

        u8 heci_client_id;

#define HECI_MEADDRESS_MKHI 7

#define HECI_MEADDRESS_PROXY 10

#define HECI_MEADDRESS_PXP 17

#define HECI_MEADDRESS_HDCP 18

Before answering the specific question here, let me explain why the design diverged compared to i915, as it will be relevant for further comments as well. One big difference in Xe is the way memory is accessed, which now requires the use of xe_map_<rd/wr>_field (instead of doing direct access via pointer dereference), for which I have created the mtl_gsc_header_<rd/wr> wrappers. This lead me to wanting to make sure that all accesses to the header are done in this file, so that we don't need to export the wrappers, as that would require including the memory paths as well and make things complicated; consequently, I don't want other files to have to include the gsc_command_header_abi.h file, as they should have no need to do any header manipulation.
If other files can't include the header, the client-specific defines need to be moved to the client-specific files. For example, HECI_MEADDRESS_MKHI is defined in gsc_mkhi_commands_abi.h in the next patch. I'd expect the other defines to also go in the respective _abi.h files.





+

+ u8 reserved1;

+

+ u16 header_version;

+#define MTL_GSC_HEADER_VERSION 1

+

+ /* FW allows host to decide host_session handle as it sees fit. */

+ u64 host_session_handle;



Also during adding this is i915 we had decided to add certain masks for PXP and HDCP

As seen here below may be add the as well



/*

         * FW allows host to decide host_session handle

         * as it sees fit.

         * For intertracebility reserving select bits(60-63)

         * to differentiate caller-target subsystem

         * 0000 - HDCP

         * 0001 - PXP Single Session

         */

        u64 host_session_handle;

#define HOST_SESSION_MASK       REG_GENMASK64(63, 60)

#define HOST_SESSION_PXP_SINGLE BIT_ULL(60)

Given the greater separation of layers (as explained above), I don't think we should special case the common code based on the caller. If we want to set part of the session id based on the heci client, then we can just encode the whole heci_client_id (see below).







+

+ /* handle generated by FW for messages that need to be re-submitted

*/

+ u64 gsc_message_handle;

+

+ u32 message_size; /* lower 20 bits only, upper 12 are reserved */

+

+ /*

+  * Flags mask:

+  * Bit 0: Pending

+  * Bit 1: Session Cleanup;

+  * Bits 2-15: Flags

+  * Bits 16-31: Extension Size

+  * According to internal spec flags are either input or output

+  * we distinguish the flags using OUTFLAG or INFLAG

+  */

+ u32 flags;

+#define GSC_OUTFLAG_MSG_PENDING BIT(0)

+#define GSC_INFLAG_MSG_CLEANUP  BIT(1)

+

+ u32 status;

+} __packed;

+

+#endif

diff --git a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h

b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h

index c7a833d7f965..f8949cad9d0f 100644

--- a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h

+++ b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h

@@ -28,6 +28,8 @@

  REG_FIELD_PREP(GSC_OPCODE, op) | \

  REG_FIELD_PREP(GSC_CMD_DATA_AND_LEN, dl))



+#define GSC_HECI_CMD_PKT __GSC_INSTR(0, 6)

+

 #define GSC_FW_LOAD __GSC_INSTR(1, 2)

 #define   GSC_FW_LOAD_LIMIT_VALID REG_BIT(31)



diff --git a/drivers/gpu/drm/xe/xe_gsc_submit.c

b/drivers/gpu/drm/xe/xe_gsc_submit.c

new file mode 100644

index 000000000000..e96336ac4728

--- /dev/null

+++ b/drivers/gpu/drm/xe/xe_gsc_submit.c

@@ -0,0 +1,170 @@

+// SPDX-License-Identifier: MIT

+/*

+ * Copyright © 2023 Intel Corporation

+ */

+

+#include "xe_gsc_submit.h"

+

+#include "abi/gsc_command_header_abi.h"

+#include "xe_bb.h"

+#include "xe_exec_queue.h"

+#include "xe_gt_printk.h"

+#include "xe_gt_types.h"

+#include "xe_map.h"

+#include "xe_sched_job.h"

+#include "instructions/xe_gsc_commands.h"

+#include "regs/xe_gsc_regs.h"

+

+#define GSC_HDR_SIZE (sizeof(struct intel_gsc_mtl_header)) /* shorthand

+define */

+

+#define mtl_gsc_header_wr(xe_, map_, offset_, field_, val_) \

+ xe_map_wr_field(xe_, map_, offset_, struct intel_gsc_mtl_header,

+field_, val_)

+

+#define mtl_gsc_header_rd(xe_, map_, offset_, field_) \

+ xe_map_rd_field(xe_, map_, offset_, struct intel_gsc_mtl_header,

+field_)

+

+static struct xe_gt *

+gsc_to_gt(struct xe_gsc *gsc)

+{

+ return container_of(gsc, struct xe_gt, uc.gsc); }

+

+/**

+ * xe_gsc_header_write - write the MTL GSC header in memory



You have define xe_gsc_header_write up in comments but the actual

Function is still called xe_gsc_emit_header one of these names need to be changed

will fix





+ * @xe: the Xe device

+ * @map: the iosys map to write to

+ * @offset: offset from the start of the map at which to write the

+header

+ * @heci_client_id: client id identifying the type of command (see abi

+for values)

+ * @host_session_id: host session ID of the caller

+ * @payload_size: size of the payload that follows the header

+ *

+ * Returns: offset memory location following the header  */

+u32 xe_gsc_emit_header(struct xe_device *xe, struct iosys_map *map, u32

offset,

+                u8 heci_client_id, u64 host_session_id, u32 payload_size) {

+ xe_map_memset(xe, map, offset, 0, GSC_HDR_SIZE);

+

+ mtl_gsc_header_wr(xe, map, offset, validity_marker,

GSC_HECI_VALIDITY_MARKER);

+ mtl_gsc_header_wr(xe, map, offset, heci_client_id, heci_client_id);

+ mtl_gsc_header_wr(xe, map, offset, host_session_handle,

host_session_id);



Also We OR the required host_session_handle with the appropriate mask

Dedpending on client id as seen below:

host_session_id &= ~HOST_SESSION_MASK;

        if (host_session_id && heci_client_id == HECI_MEADDRESS_PXP)

                host_session_id |= HOST_SESSION_PXP_SINGLE;

any reason to move away from this as it was decided we will have it here in a common place

Continuing from the comment above, this could become:



#define HOST_SESSION_MASK       REG_GENMASK64(63, 56)



xe_assert(xe, !(host_session_id & HOST_SESSION_MASK));



if (host_session_id)

       host_session_id |= FIELD_PREP(HOST_SESSION_MASK, heci_client_id);

>That way we can identify the client that generated the session without having to >special-case. Does that work for you?

That should work and other things suggested sound fair too

Regards,
Suraj Kandpal


Daniele







Regards,

Suraj Kandpal



+ mtl_gsc_header_wr(xe, map, offset, header_version,

MTL_GSC_HEADER_VERSION);

+ mtl_gsc_header_wr(xe, map, offset, message_size, payload_size +

+GSC_HDR_SIZE);

+

+ return offset + GSC_HDR_SIZE;

+};

+

+/**

+ * xe_gsc_check_and_update_pending - check the pending bit and update

+the input

+ * header with the retry handle from the output header

+ * @xe: the Xe device

+ * @in: the iosys map containing the input buffer

+ * @offset_in: offset within the iosys at which the input buffer is

+located

+ * @out: the iosys map containing the output buffer

+ * @offset_out: offset within the iosys at which the output buffer is

+located

+ *

+ * Returns: true if the pending bit was set, false otherwise  */ bool

+xe_gsc_check_and_update_pending(struct xe_device *xe,

+                             struct iosys_map *in, u32 offset_in,

+                             struct iosys_map *out, u32 offset_out) {

+ if (mtl_gsc_header_rd(xe, out, offset_out, flags) &

GSC_OUTFLAG_MSG_PENDING) {

+         u64 handle = mtl_gsc_header_rd(xe, out, offset_out,

+gsc_message_handle);

+

+         mtl_gsc_header_wr(xe, in, offset_in, gsc_message_handle,

handle);

+

+         return true;

+ }

+

+ return false;

+}

+

+/**

+ * xe_gsc_read_out_header - reads and validates the output header and

+returns

+ * the offset of the reply following the header

+ * @xe: the Xe device

+ * @map: the iosys map containing the output buffer

+ * @offset: offset within the iosys at which the output buffer is

+located

+ * @min_payload_size: minimum size of the message excluding the gsc

+header

+ * @payload_offset: optional pointer to be set to the payload offset

+ *

+ * Returns: -errno value on failure, 0 otherwise  */ int

+xe_gsc_read_out_header(struct xe_device *xe,

+                    struct iosys_map *map, u32 offset,

+                    u32 min_payload_size,

+                    u32 *payload_offset)

+{

+ u32 marker = mtl_gsc_header_rd(xe, map, offset, validity_marker);

+ u32 size = mtl_gsc_header_rd(xe, map, offset, message_size);

+ u32 payload_size = size - GSC_HDR_SIZE;

+

+ if (marker != GSC_HECI_VALIDITY_MARKER)

+         return -EPROTO;

+

+ if (size < GSC_HDR_SIZE || payload_size < min_payload_size)

+         return -ENODATA;

+

+ if (payload_offset)

+         *payload_offset = offset + GSC_HDR_SIZE;

+

+ return 0;

+}

+

+/**

+ * xe_gsc_pkt_submit_kernel - submit a kernel heci pkt to the GSC

+ * @xe: the GSC uC

+ * @addr_in: GGTT address of the message to send to the GSC

+ * @size_in: size of the message to send to the GSC

+ * @addr_out: GGTT address for the GSC to write the reply to

+ * @size_out: size of the memory reserved for the reply  */ int

+xe_gsc_pkt_submit_kernel(struct xe_gsc *gsc, u64 addr_in, u32 size_in,

+                      u64 addr_out, u32 size_out)

+{

+ struct xe_gt *gt = gsc_to_gt(gsc);

+ struct xe_bb *bb;

+ struct xe_sched_job *job;

+ struct dma_fence *fence;

+ long timeout;

+

+ if (size_in < GSC_HDR_SIZE)

+         return -ENODATA;

+

+ if (size_out < GSC_HDR_SIZE)

+         return -ENOMEM;

+

+ bb = xe_bb_new(gt, 8, false);

+ if (IS_ERR(bb))

+         return PTR_ERR(bb);

+

+ bb->cs[bb->len++] = GSC_HECI_CMD_PKT;

+ bb->cs[bb->len++] = lower_32_bits(addr_in);

+ bb->cs[bb->len++] = upper_32_bits(addr_in);

+ bb->cs[bb->len++] = size_in;

+ bb->cs[bb->len++] = lower_32_bits(addr_out);

+ bb->cs[bb->len++] = upper_32_bits(addr_out);

+ bb->cs[bb->len++] = size_out;

+ bb->cs[bb->len++] = 0;

+

+ job = xe_bb_create_job(gsc->q, bb);

+ if (IS_ERR(job)) {

+         xe_bb_free(bb, NULL);

+         return PTR_ERR(job);

+ }

+

+ xe_sched_job_arm(job);

+ fence = dma_fence_get(&job->drm.s_fence->finished);

+ xe_sched_job_push(job);

+

+ timeout = dma_fence_wait_timeout(fence, false, HZ);

+ dma_fence_put(fence);

+ xe_bb_free(bb, NULL);

+ if (timeout < 0)

+         return timeout;

+ else if (!timeout)

+         return -ETIME;

+

+ return 0;

+}

diff --git a/drivers/gpu/drm/xe/xe_gsc_submit.h

b/drivers/gpu/drm/xe/xe_gsc_submit.h

new file mode 100644

index 000000000000..0801da5d446a

--- /dev/null

+++ b/drivers/gpu/drm/xe/xe_gsc_submit.h

@@ -0,0 +1,30 @@

+/* SPDX-License-Identifier: MIT */

+/*

+ * Copyright © 2023 Intel Corporation

+ */

+

+#ifndef _XE_GSC_SUBMIT_H_

+#define _XE_GSC_SUBMIT_H_

+

+#include <linux/types.h>

+

+struct iosys_map;

+struct xe_device;

+struct xe_gsc;

+

+u32 xe_gsc_emit_header(struct xe_device *xe, struct iosys_map *map, u32

offset,

+                u8 heci_client_id, u64 host_session_id, u32 payload_size);

+

+bool xe_gsc_check_and_update_pending(struct xe_device *xe,

+                             struct iosys_map *in, u32 offset_in,

+                             struct iosys_map *out, u32 offset_out);

+

+int xe_gsc_read_out_header(struct xe_device *xe,

+                    struct iosys_map *map, u32 offset,

+                    u32 min_payload_size,

+                    u32 *payload_offset);

+

+int xe_gsc_pkt_submit_kernel(struct xe_gsc *gsc, u64 addr_in, u32 size_in,

+                      u64 addr_out, u32 size_out);

+

+#endif

--

2.41.0




[-- Attachment #2: Type: text/html, Size: 30425 bytes --]

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

* Re: [Intel-xe] [PATCH 01/12] drm/xe: implement driver initiated function-reset
  2023-11-07 23:46   ` John Harrison
@ 2023-11-08 18:14     ` Daniele Ceraolo Spurio
  0 siblings, 0 replies; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-08 18:14 UTC (permalink / raw)
  To: John Harrison, intel-xe; +Cc: Andrzej Hajda



On 11/7/2023 3:46 PM, John Harrison wrote:
> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>> From: Andrzej Hajda <andrzej.hajda@intel.com>
>>
>> Driver initiated function-reset (FLR) is the highest level of reset
>> that we can trigger from within the driver. In contrast to PCI FLR it
>> doesn't require re-enumeration of PCI BAR. It can be useful in case
>> GT fails to reset. It is also the only way to trigger GSC reset from
>> the driver and can be used in future addition of GSC support.
>>
>> v2:
>>    - use regs from xe_regs.h
>>    - move the flag to xe.mmio
>>    - call flr only on root gt
>>    - use BIOS protection check
>>    - copy/paste comments from i915
>> v3:
>>    - flr code moved to xe_device.c
>> v4:
>>    - needs_flr_on_fini moved to xe_device
>>
>> Signed-off-by: Andrzej Hajda <andrzej.hajda@intel.com>
>> Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> ---
>>   drivers/gpu/drm/xe/regs/xe_regs.h    |  7 +++
>>   drivers/gpu/drm/xe/xe_device.c       | 78 ++++++++++++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_device_types.h |  3 ++
>>   drivers/gpu/drm/xe/xe_gt.c           |  2 +
>>   4 files changed, 90 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/xe/regs/xe_regs.h 
>> b/drivers/gpu/drm/xe/regs/xe_regs.h
>> index 2240cd157603..a646d13af03a 100644
>> --- a/drivers/gpu/drm/xe/regs/xe_regs.h
>> +++ b/drivers/gpu/drm/xe/regs/xe_regs.h
>> @@ -57,8 +57,15 @@
>>     #define SOFTWARE_FLAGS_SPR33            XE_REG(0x4f084)
>>   +#define GU_CNTL_PROTECTED            XE_REG(0x10100C)
>> +#define   DRIVERINT_FLR_DIS            REG_BIT(31)
>> +
>>   #define GU_CNTL                    XE_REG(0x101010)
>>   #define   LMEM_INIT                REG_BIT(7)
>> +#define   DRIVERFLR                REG_BIT(31)
>> +
>> +#define GU_DEBUG                XE_REG(0x101018)
>> +#define   DRIVERFLR_STATUS            REG_BIT(31)
>>     #define XEHP_CLOCK_GATE_DIS            XE_REG(0x101014)
>>   #define   SGSI_SIDECLK_DIS            REG_BIT(17)
>> diff --git a/drivers/gpu/drm/xe/xe_device.c 
>> b/drivers/gpu/drm/xe/xe_device.c
>> index 8341acf66e5f..515cdf599fab 100644
>> --- a/drivers/gpu/drm/xe/xe_device.c
>> +++ b/drivers/gpu/drm/xe/xe_device.c
>> @@ -5,6 +5,8 @@
>>     #include "xe_device.h"
>>   +#include <linux/units.h>
>> +
>>   #include <drm/drm_aperture.h>
>>   #include <drm/drm_atomic_helper.h>
>>   #include <drm/drm_gem_ttm_helper.h>
>> @@ -260,6 +262,78 @@ struct xe_device *xe_device_create(struct 
>> pci_dev *pdev,
>>       return ERR_PTR(err);
>>   }
>>   +/*
>> + * The driver-initiated FLR is the highest level of reset that we 
>> can trigger
>> + * from within the driver. It is different from the PCI FLR in that 
>> it doesn't
>> + * fully reset the SGUnit and doesn't modify the PCI config space 
>> and therefore
>> + * it doesn't require a re-enumeration of the PCI BARs. However, the
>> + * driver-initiated FLR does still cause a reset of both GT and 
>> display and a
>> + * memory wipe of local and stolen memory, so recovery would require 
>> a full HW
>> + * re-init and saving/restoring (or re-populating) the wiped memory. 
>> Since we
>> + * perform the FLR as the very last action before releasing access 
>> to the HW
>> + * during the driver release flow, we don't attempt recovery at all, 
>> because
>> + * if/when a new instance of i915 is bound to the device it will do 
>> a full
>> + * re-init anyway.
>> + */
>> +static void xe_driver_flr(struct xe_device *xe)
>> +{
>> +    const unsigned int flr_timeout = 3 * MICRO; /* specs recommend a 
>> 3s wait */
> 3s or 3us?

MICRO is the number of usecs in a sec, so that matches 3 seconds as a 
usec value

>
> And is it supposed to be the same timeout for both registers?

The spec says that the whole process can take up to 3 secs, but there is 
no indication on how this time is split across the 2 waits. We could 
subtract the amount waited on the first wait from the timeout of the 
second one, but that has very little benefit because if the FLR fails 
the HW is dead anyway, so it doesn't really matter if we notice a bit 
later; given that, it's just easier code-wise to have the full 3 secs as 
timeout both times.

Daniele

>
> John.
>
>> +    struct xe_gt *gt = xe_root_mmio_gt(xe);
>> +    int ret;
>> +
>> +    if (xe_mmio_read32(gt, GU_CNTL_PROTECTED) & DRIVERINT_FLR_DIS) {
>> +        drm_info_once(&xe->drm, "BIOS Disabled Driver-FLR\n");
>> +        return;
>> +    }
>> +
>> +    drm_dbg(&xe->drm, "Triggering Driver-FLR\n");
>> +
>> +    /*
>> +     * Make sure any pending FLR requests have cleared by waiting 
>> for the
>> +     * FLR trigger bit to go to zero. Also clear GU_DEBUG's 
>> DRIVERFLR_STATUS
>> +     * to make sure it's not still set from a prior attempt (it's a 
>> write to
>> +     * clear bit).
>> +     * Note that we should never be in a situation where a previous 
>> attempt
>> +     * is still pending (unless the HW is totally dead), but better 
>> to be
>> +     * safe in case something unexpected happens
>> +     */
>> +    ret = xe_mmio_wait32(gt, GU_CNTL, DRIVERFLR, 0, flr_timeout, 
>> NULL, false);
>> +    if (ret) {
>> +        drm_err(&xe->drm, "Driver-FLR-prepare wait for ready failed! 
>> %d\n", ret);
>> +        return;
>> +    }
>> +    xe_mmio_write32(gt, GU_DEBUG, DRIVERFLR_STATUS);
>> +
>> +    /* Trigger the actual Driver-FLR */
>> +    xe_mmio_rmw32(gt, GU_CNTL, 0, DRIVERFLR);
>> +
>> +    /* Wait for hardware teardown to complete */
>> +    ret = xe_mmio_wait32(gt, GU_CNTL, DRIVERFLR, 0, flr_timeout, 
>> NULL, false);
>> +    if (ret) {
>> +        drm_err(&xe->drm, "Driver-FLR-teardown wait completion 
>> failed! %d\n", ret);
>> +        return;
>> +    }
>> +
>> +    /* Wait for hardware/firmware re-init to complete */
>> +    ret = xe_mmio_wait32(gt, GU_DEBUG, DRIVERFLR_STATUS, 
>> DRIVERFLR_STATUS,
>> +                 flr_timeout, NULL, false);
>> +    if (ret) {
>> +        drm_err(&xe->drm, "Driver-FLR-reinit wait completion failed! 
>> %d\n", ret);
>> +        return;
>> +    }
>> +
>> +    /* Clear sticky completion status */
>> +    xe_mmio_write32(gt, GU_DEBUG, DRIVERFLR_STATUS);
>> +}
>> +
>> +static void xe_driver_flr_fini(struct drm_device *drm, void *arg)
>> +{
>> +    struct xe_device *xe = arg;
>> +
>> +    if (xe->needs_flr_on_fini)
>> +        xe_driver_flr(xe);
>> +}
>> +
>>   static void xe_device_sanitize(struct drm_device *drm, void *arg)
>>   {
>>       struct xe_device *xe = arg;
>> @@ -294,6 +368,10 @@ int xe_device_probe(struct xe_device *xe)
>>       if (err)
>>           return err;
>>   +    err = drmm_add_action_or_reset(&xe->drm, xe_driver_flr_fini, xe);
>> +    if (err)
>> +        return err;
>> +
>>       for_each_gt(gt, xe, id) {
>>           err = xe_pcode_probe(gt);
>>           if (err)
>> diff --git a/drivers/gpu/drm/xe/xe_device_types.h 
>> b/drivers/gpu/drm/xe/xe_device_types.h
>> index 44d622d4cc3a..9a0b0ccc1018 100644
>> --- a/drivers/gpu/drm/xe/xe_device_types.h
>> +++ b/drivers/gpu/drm/xe/xe_device_types.h
>> @@ -405,6 +405,9 @@ struct xe_device {
>>       /** @heci_gsc: graphics security controller */
>>       struct xe_heci_gsc heci_gsc;
>>   +    /** @needs_flr_on_fini: requests function-reset on fini */
>> +    bool needs_flr_on_fini;
>> +
>>       /* private: */
>>     #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
>> diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
>> index d380f67b3365..73c090762771 100644
>> --- a/drivers/gpu/drm/xe/xe_gt.c
>> +++ b/drivers/gpu/drm/xe/xe_gt.c
>> @@ -626,6 +626,8 @@ static int gt_reset(struct xe_gt *gt)
>> xe_uevent_gt_reset_failure(to_pci_dev(gt_to_xe(gt)->drm.dev),
>>                      gt_to_tile(gt)->id, gt->info.id);
>>   +    gt_to_xe(gt)->needs_flr_on_fini = true;
>> +
>>       return err;
>>   }
>


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

* Re: [Intel-xe] [PATCH 06/12] drm/xe/gsc: GSC FW load
  2023-10-27 22:29 ` [Intel-xe] [PATCH 06/12] drm/xe/gsc: GSC FW load Daniele Ceraolo Spurio
@ 2023-11-08 22:17   ` John Harrison
  2023-11-08 22:23     ` Daniele Ceraolo Spurio
  0 siblings, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-08 22:17 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> The GSC FW must be copied in a 4MB stolen memory allocation, whose GGTT
> address is then passed as a parameter to a dedicated load instruction
> submitted via the GSC engine.
>
> Since the GSC load is relatively slow (up to 250ms), we perform it
> asynchronously via a worker. This requires us to make sure that the
> worker has stopped before suspending/unloading.
>
> Note that we can't yet use xe_migrate_copy for the copy because it
> doesn't work with stolen memory right now, so we do a memcpy from the
> CPU side instead.
>
> Bspec: 65306, 65346
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
> Cc: John Harrison <John.C.Harrison@Intel.com>
> ---
>   .../gpu/drm/xe/instructions/xe_gsc_commands.h |  34 +++
>   .../gpu/drm/xe/instructions/xe_instr_defs.h   |   1 +
>   drivers/gpu/drm/xe/regs/xe_gsc_regs.h         |  29 +++
>   drivers/gpu/drm/xe/xe_gsc.c                   | 240 ++++++++++++++++++
>   drivers/gpu/drm/xe/xe_gsc.h                   |   3 +
>   drivers/gpu/drm/xe/xe_gsc_types.h             |  17 ++
>   drivers/gpu/drm/xe/xe_uc.c                    |  12 +-
>   7 files changed, 335 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>   create mode 100644 drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>
> diff --git a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
> new file mode 100644
> index 000000000000..c7a833d7f965
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
> @@ -0,0 +1,34 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef _XE_GSC_COMMANDS_H_
> +#define _XE_GSC_COMMANDS_H_
> +
> +#include "instructions/xe_instr_defs.h"
> +
> +/*
> + * All GSCCS-specific commands have fixed length, so we can include it in the
> + * defines. Note that the generic GSC command header structure includes an
> + * optional data field in bits 9-21, but there are no commands that actually use
> + * it; some of the commands are instead defined as having an extended length
> + * field spanning bits 0-15, even if the extra bits are not required because the
> + * longest GSCCS command is only 8 dwords. To handle this, the defines below use
> + * a single field for both data and len. If we ever get a commands that does
> + * actually have data and this approach doesn't work for it we can re-work it
> + * at that point.
> + */
> +
> +#define GSC_OPCODE		REG_GENMASK(28, 22)
> +#define GSC_CMD_DATA_AND_LEN	REG_GENMASK(21, 0)
> +
> +#define __GSC_INSTR(op, dl) \
> +	(XE_INSTR_GSC | \
> +	REG_FIELD_PREP(GSC_OPCODE, op) | \
> +	REG_FIELD_PREP(GSC_CMD_DATA_AND_LEN, dl))
> +
> +#define GSC_FW_LOAD __GSC_INSTR(1, 2)
> +#define   GSC_FW_LOAD_LIMIT_VALID REG_BIT(31)
> +
> +#endif
> diff --git a/drivers/gpu/drm/xe/instructions/xe_instr_defs.h b/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
> index e403b4fcc20a..04179b2a48e1 100644
> --- a/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
> +++ b/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
> @@ -15,6 +15,7 @@
>    */
>   #define XE_INSTR_CMD_TYPE		GENMASK(31, 29)
>   #define   XE_INSTR_MI			REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x0)
> +#define   XE_INSTR_GSC			REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x2)
>   #define   XE_INSTR_GFXPIPE		REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x3)
>   
>   /*
> diff --git a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
> new file mode 100644
> index 000000000000..22d2ad9cb64d
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef _XE_GSC_REGS_H_
> +#define _XE_GSC_REGS_H_
> +
> +#include <linux/compiler.h>
> +#include <linux/types.h>
> +
> +#include "regs/xe_reg_defs.h"
> +
> +/* Definitions of GSC H/W registers, bits, etc */
> +
> +#define MTL_GSC_HECI1_BASE	0x00116000
> +#define MTL_GSC_HECI2_BASE	0x00117000
> +
> +/*
> + * The FWSTS register values are FW defined and can be different between
> + * HECI1 and HECI2
> + */
> +#define HECI_FWSTS1(base)				XE_REG((base) + 0xc40)
> +#define   HECI1_FWSTS1_CURRENT_STATE			REG_GENMASK(3, 0)
> +#define   HECI1_FWSTS1_CURRENT_STATE_RESET		0
> +#define   HECI1_FWSTS1_PROXY_STATE_NORMAL		5
> +#define   HECI1_FWSTS1_INIT_COMPLETE			REG_BIT(9)
> +
> +#endif
> diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
> index 3f709577d73b..7e5ba9039163 100644
> --- a/drivers/gpu/drm/xe/xe_gsc.c
> +++ b/drivers/gpu/drm/xe/xe_gsc.c
> @@ -5,10 +5,20 @@
>   
>   #include "xe_gsc.h"
>   
> +#include <drm/drm_managed.h>
> +
> +#include "xe_bb.h"
> +#include "xe_bo.h"
>   #include "xe_device.h"
> +#include "xe_exec_queue.h"
>   #include "xe_gt.h"
>   #include "xe_gt_printk.h"
> +#include "xe_map.h"
> +#include "xe_mmio.h"
> +#include "xe_sched_job.h"
>   #include "xe_uc_fw.h"
> +#include "instructions/xe_gsc_commands.h"
> +#include "regs/xe_gsc_regs.h"
>   
>   static struct xe_gt *
>   gsc_to_gt(struct xe_gsc *gsc)
> @@ -16,6 +26,134 @@ gsc_to_gt(struct xe_gsc *gsc)
>   	return container_of(gsc, struct xe_gt, uc.gsc);
>   }
>   
> +static int memcpy_fw(struct xe_gsc *gsc)
> +{
> +	struct xe_gt *gt = gsc_to_gt(gsc);
> +	struct xe_device *xe = gt_to_xe(gt);
> +	u32 fw_size = gsc->fw.size;
> +	void *storage;
> +
> +	/*
> +	 * FIXME: xe_migrate_copy does not work with stolen mem yet, so we use
> +	 * a memcpy for now.
> +	 */
> +	storage = kmalloc(fw_size, GFP_KERNEL);
> +	if (!storage)
> +		return -ENOMEM;
> +
> +	xe_map_memcpy_from(xe, storage, &gsc->fw.bo->vmap, 0, fw_size);
> +	xe_map_memcpy_to(xe, &gsc->private->vmap, 0, storage, fw_size);
> +	xe_map_memset(xe, &gsc->private->vmap, fw_size, 0, gsc->private->size - fw_size);
> +
> +	kfree(storage);
> +
> +	return 0;
> +}
> +
> +static int emit_gsc_upload(struct xe_gsc *gsc)
> +{
> +	struct xe_gt *gt = gsc_to_gt(gsc);
> +	u32 offset = xe_bo_ggtt_addr(gsc->private);
> +	struct xe_bb *bb;
> +	struct xe_sched_job *job;
> +	struct dma_fence *fence;
> +	long timeout;
> +
> +	bb = xe_bb_new(gt, 4, false);
> +	if (IS_ERR(bb))
> +		return PTR_ERR(bb);
> +
> +	bb->cs[bb->len++] = GSC_FW_LOAD;
> +	bb->cs[bb->len++] = lower_32_bits(offset);
> +	bb->cs[bb->len++] = upper_32_bits(offset);
> +	bb->cs[bb->len++] = (gsc->private->size / SZ_4K) | GSC_FW_LOAD_LIMIT_VALID;
> +
> +	job = xe_bb_create_job(gsc->q, bb);
> +	if (IS_ERR(job)) {
> +		xe_bb_free(bb, NULL);
> +		return PTR_ERR(job);
> +	}
> +
> +	xe_sched_job_arm(job);
> +	fence = dma_fence_get(&job->drm.s_fence->finished);
> +	xe_sched_job_push(job);
> +
> +	timeout = dma_fence_wait_timeout(fence, false, HZ);
> +	dma_fence_put(fence);
> +	xe_bb_free(bb, NULL);
> +	if (timeout < 0)
> +		return timeout;
> +	else if (!timeout)
> +		return -ETIME;
> +
> +	return 0;
> +}
> +
> +static int gsc_fw_is_loaded(struct xe_gt *gt)
> +{
> +	return xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)) &
> +			      HECI1_FWSTS1_INIT_COMPLETE;
> +}
> +
> +static int gsc_fw_wait(struct xe_gt *gt)
> +{
> +	return xe_mmio_wait32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE),
> +			      HECI1_FWSTS1_INIT_COMPLETE,
> +			      HECI1_FWSTS1_INIT_COMPLETE,
> +			      500, NULL, false);
The 500 at least needs a comment to explain where it comes from and why. 
If not a #define as well.

I assume this is the <=250ms in the commit description?

> +}
> +
> +static int gsc_upload(struct xe_gsc *gsc)
> +{
> +	struct xe_gt *gt = gsc_to_gt(gsc);
> +	int err;
> +
> +	if (XE_WARN_ON(!xe_uc_fw_is_loadable(&gsc->fw) || !gsc->q || gsc_fw_is_loaded(gt)))
The last term here is a register read of a firmware written value? The 
kernel should not barf with WARNs and such due to external data. Those 
are for internal bugs only. Dodgy external data should just be an 
xe_gt_err, shouldn't it?

> +		return 0;
And returning zero means the state will transition to TRANSFERRED not 
LOAD_FAIL. That seems plausible in the case of already loaded, but in 
the other cases that seems wrong?

John.

> +
> +	err = memcpy_fw(gsc);
> +	if (err) {
> +		xe_gt_err(gt, "Failed to memcpy GSC FW\n");
> +		return err;
> +	}
> +
> +	err = emit_gsc_upload(gsc);
> +	if (err) {
> +		xe_gt_err(gt, "Failed to emit GSC FW upload (%pe)\n", ERR_PTR(err));
> +		return err;
> +	}
> +
> +	err = gsc_fw_wait(gt);
> +	if (err) {
> +		xe_gt_err(gt, "Failed to wait for GSC load (%pe)\n", ERR_PTR(err));
> +		return err;
> +	}
> +
> +	xe_gt_dbg(gt, "GSC FW async load completed\n");
> +
> +	return 0;
> +}
> +
> +static void gsc_work(struct work_struct *work)
> +{
> +	struct xe_gsc *gsc = container_of(work, typeof(*gsc), work);
> +	struct xe_gt *gt = gsc_to_gt(gsc);
> +	struct xe_device *xe = gt_to_xe(gt);
> +	int ret;
> +
> +	xe_device_mem_access_get(xe);
> +	xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC);
> +
> +	ret = gsc_upload(gsc);
> +	if (ret)
> +		xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_LOAD_FAIL);
> +	else
> +		xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
> +
> +	xe_force_wake_put(gt_to_fw(gt), XE_FW_GSC);
> +	xe_device_mem_access_put(xe);
> +}
> +
>   int xe_gsc_init(struct xe_gsc *gsc)
>   {
>   	struct xe_gt *gt = gsc_to_gt(gsc);
> @@ -23,6 +161,7 @@ int xe_gsc_init(struct xe_gsc *gsc)
>   	int ret;
>   
>   	gsc->fw.type = XE_UC_FW_TYPE_GSC;
> +	INIT_WORK(&gsc->work, gsc_work);
>   
>   	/* The GSC uC is only available on the media GT */
>   	if (tile->media_gt && (gt != tile->media_gt)) {
> @@ -48,3 +187,104 @@ int xe_gsc_init(struct xe_gsc *gsc)
>   	return ret;
>   }
>   
> +static void free_resources(struct drm_device *drm, void *arg)
> +{
> +	struct xe_gsc *gsc = arg;
> +
> +	if (gsc->wq) {
> +		destroy_workqueue(gsc->wq);
> +		gsc->wq = NULL;
> +	}
> +
> +	if (gsc->q) {
> +		xe_exec_queue_put(gsc->q);
> +		gsc->q = NULL;
> +	}
> +
> +	if (gsc->private) {
> +		xe_bo_unpin_map_no_vm(gsc->private);
> +		gsc->private = NULL;
> +	}
> +}
> +
> +int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc)
> +{
> +	struct xe_gt *gt = gsc_to_gt(gsc);
> +	struct xe_tile *tile = gt_to_tile(gt);
> +	struct xe_device *xe = gt_to_xe(gt);
> +	struct xe_hw_engine *hwe = xe_gt_hw_engine(gt, XE_ENGINE_CLASS_OTHER, 0, true);
> +	struct xe_exec_queue *q;
> +	struct workqueue_struct *wq;
> +	struct xe_bo *bo;
> +	int err;
> +
> +	if (!xe_uc_fw_is_available(&gsc->fw))
> +		return 0;
> +
> +	if (!hwe)
> +		return -ENODEV;
> +
> +	bo = xe_bo_create_pin_map(xe, tile, NULL, SZ_4M,
> +				  ttm_bo_type_kernel,
> +				  XE_BO_CREATE_STOLEN_BIT |
> +				  XE_BO_CREATE_GGTT_BIT);
> +	if (IS_ERR(bo))
> +		return PTR_ERR(bo);
> +
> +	q = xe_exec_queue_create(xe, NULL,
> +				 BIT(hwe->logical_instance), 1, hwe,
> +				 EXEC_QUEUE_FLAG_KERNEL |
> +				 EXEC_QUEUE_FLAG_PERMANENT);
> +	if (IS_ERR(q)) {
> +		xe_gt_err(gt, "Failed to create queue for GSC submission\n");
> +		err = PTR_ERR(q);
> +		goto out_bo;
> +	}
> +
> +	wq = alloc_ordered_workqueue("gsc-ordered-wq", 0);
> +	if (!wq) {
> +		err = -ENOMEM;
> +		goto out_q;
> +	}
> +
> +	gsc->private = bo;
> +	gsc->q = q;
> +	gsc->wq = wq;
> +
> +	err = drmm_add_action_or_reset(&xe->drm, free_resources, gsc);
> +	if (err)
> +		return err;
> +
> +	xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_LOADABLE);
> +
> +	return 0;
> +
> +out_q:
> +	xe_exec_queue_put(q);
> +out_bo:
> +	xe_bo_unpin_map_no_vm(bo);
> +	return err;
> +
> +}
> +
> +void xe_gsc_load_start(struct xe_gsc *gsc)
> +{
> +	struct xe_gt *gt = gsc_to_gt(gsc);
> +
> +	if (!xe_uc_fw_is_loadable(&gsc->fw) || !gsc->q)
> +		return;
> +
> +	/* GSC FW survives GT reset and D3Hot */
> +	if (gsc_fw_is_loaded(gt)) {
> +		xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
> +		return;
> +	}
> +
> +	queue_work(gsc->wq, &gsc->work);
> +}
> +
> +void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc)
> +{
> +	if (xe_uc_fw_is_loadable(&gsc->fw) && gsc->wq)
> +		flush_work(&gsc->work);
> +}
> diff --git a/drivers/gpu/drm/xe/xe_gsc.h b/drivers/gpu/drm/xe/xe_gsc.h
> index baa7f21f4204..f870eddc77d4 100644
> --- a/drivers/gpu/drm/xe/xe_gsc.h
> +++ b/drivers/gpu/drm/xe/xe_gsc.h
> @@ -9,5 +9,8 @@
>   #include "xe_gsc_types.h"
>   
>   int xe_gsc_init(struct xe_gsc *gsc);
> +int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc);
> +void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc);
> +void xe_gsc_load_start(struct xe_gsc *gsc);
>   
>   #endif
> diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h b/drivers/gpu/drm/xe/xe_gsc_types.h
> index 1bc50583fe58..57fefd66a7ea 100644
> --- a/drivers/gpu/drm/xe/xe_gsc_types.h
> +++ b/drivers/gpu/drm/xe/xe_gsc_types.h
> @@ -6,8 +6,13 @@
>   #ifndef _XE_GSC_TYPES_H_
>   #define _XE_GSC_TYPES_H_
>   
> +#include <linux/workqueue.h>
> +
>   #include "xe_uc_fw_types.h"
>   
> +struct xe_bo;
> +struct xe_exec_queue;
> +
>   /**
>    * struct xe_gsc - GSC
>    */
> @@ -17,6 +22,18 @@ struct xe_gsc {
>   
>   	/** @security_version: SVN found in the fetched blob */
>   	u32 security_version;
> +
> +	/** @private: Private data for use by the GSC FW */
> +	struct xe_bo *private;
> +
> +	/** @q: Default queue used for submissions to GSC FW */
> +	struct xe_exec_queue *q;
> +
> +	/** @wq: workqueue to handle jobs for delayed load and proxy handling */
> +	struct workqueue_struct *wq;
> +
> +	/** @work: delayed load and proxy handling work */
> +	struct work_struct work;
>   };
>   
>   #endif
> diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
> index b67154c78dff..15dcd1f91e9c 100644
> --- a/drivers/gpu/drm/xe/xe_uc.c
> +++ b/drivers/gpu/drm/xe/xe_uc.c
> @@ -74,11 +74,17 @@ int xe_uc_init(struct xe_uc *uc)
>    */
>   int xe_uc_init_post_hwconfig(struct xe_uc *uc)
>   {
> +	int err;
> +
>   	/* GuC submission not enabled, nothing to do */
>   	if (!xe_device_uc_enabled(uc_to_xe(uc)))
>   		return 0;
>   
> -	return xe_guc_init_post_hwconfig(&uc->guc);
> +	err = xe_guc_init_post_hwconfig(&uc->guc);
> +	if (err)
> +		return err;
> +
> +	return xe_gsc_init_post_hwconfig(&uc->gsc);
>   }
>   
>   static int uc_reset(struct xe_uc *uc)
> @@ -173,6 +179,9 @@ int xe_uc_init_hw(struct xe_uc *uc)
>   	ret = xe_huc_auth(&uc->huc);
>   	xe_gt_assert(uc_to_gt(uc), !ret);
>   
> +	/* GSC load is async */
> +	xe_gsc_load_start(&uc->gsc);
> +
>   	return 0;
>   }
>   
> @@ -197,6 +206,7 @@ void xe_uc_gucrc_disable(struct xe_uc *uc)
>   
>   void xe_uc_stop_prepare(struct xe_uc *uc)
>   {
> +	xe_gsc_wait_for_worker_completion(&uc->gsc);
>   	xe_guc_stop_prepare(&uc->guc);
>   }
>   


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

* Re: [Intel-xe] [PATCH 07/12] drm/xe/gsc: Implement WA 14015076503
  2023-10-27 22:29 ` [Intel-xe] [PATCH 07/12] drm/xe/gsc: Implement WA 14015076503 Daniele Ceraolo Spurio
@ 2023-11-08 22:22   ` John Harrison
  2023-11-08 22:35     ` Daniele Ceraolo Spurio
  0 siblings, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-08 22:22 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> When the GSC FW is loaded, we need to inform it when a GSCCS reset is
> coming and then wait 200ms for it to get ready to process the reset.
>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: John Harrison <john.c.harrison@intel.com>
> ---
>   drivers/gpu/drm/xe/Makefile           |  2 +-
>   drivers/gpu/drm/xe/regs/xe_gsc_regs.h | 10 ++++++
>   drivers/gpu/drm/xe/xe_gt.c            | 44 +++++++++++++++++++++++++++
>   drivers/gpu/drm/xe/xe_wa_oob.rules    |  1 +
>   4 files changed, 56 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
> index 474b6044d054..4a442dcf4d79 100644
> --- a/drivers/gpu/drm/xe/Makefile
> +++ b/drivers/gpu/drm/xe/Makefile
> @@ -37,7 +37,7 @@ quiet_cmd_wa_oob = GEN     $(notdir $(generated_oob))
>   $(generated_oob) &: $(obj)/xe_gen_wa_oob $(srctree)/$(src)/xe_wa_oob.rules
>   	$(call cmd,wa_oob)
>   
> -$(obj)/xe_guc.o $(obj)/xe_migrate.o $(obj)/xe_ring_ops.o $(obj)/xe_vm.o $(obj)/xe_wa.o: $(generated_oob)
> +$(obj)/xe_gt.o $(obj)/xe_guc.o $(obj)/xe_migrate.o $(obj)/xe_ring_ops.o $(obj)/xe_vm.o $(obj)/xe_wa.o: $(generated_oob)
Is it not worth splitting this into multiple lines?

>   
>   # Please keep these build lists sorted!
>   
> diff --git a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
> index 22d2ad9cb64d..9a84b55d66ee 100644
> --- a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
> +++ b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
> @@ -16,6 +16,13 @@
>   #define MTL_GSC_HECI1_BASE	0x00116000
>   #define MTL_GSC_HECI2_BASE	0x00117000
>   
> +#define HECI_H_CSR(base)	XE_REG((base) + 0x4)
> +#define   HECI_H_CSR_IE		REG_BIT(0)
> +#define   HECI_H_CSR_IS		REG_BIT(1)
> +#define   HECI_H_CSR_IG		REG_BIT(2)
> +#define   HECI_H_CSR_RDY	REG_BIT(3)
> +#define   HECI_H_CSR_RST	REG_BIT(4)
> +
>   /*
>    * The FWSTS register values are FW defined and can be different between
>    * HECI1 and HECI2
> @@ -26,4 +33,7 @@
>   #define   HECI1_FWSTS1_PROXY_STATE_NORMAL		5
>   #define   HECI1_FWSTS1_INIT_COMPLETE			REG_BIT(9)
>   
> +#define HECI_H_GS1(base)	XE_REG((base) + 0xc4c)
> +#define   HECI_H_GS1_ER_PREP	REG_BIT(0)
> +
>   #endif
> diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
> index 73c090762771..0e8e24bded1c 100644
> --- a/drivers/gpu/drm/xe/xe_gt.c
> +++ b/drivers/gpu/drm/xe/xe_gt.c
> @@ -10,8 +10,10 @@
>   #include <drm/drm_managed.h>
>   #include <drm/xe_drm.h>
>   
> +#include "generated/xe_wa_oob.h"
>   #include "instructions/xe_gfxpipe_commands.h"
>   #include "instructions/xe_mi_commands.h"
> +#include "regs/xe_gsc_regs.h"
>   #include "regs/xe_gt_regs.h"
>   #include "xe_assert.h"
>   #include "xe_bb.h"
> @@ -504,16 +506,58 @@ int xe_gt_init(struct xe_gt *gt)
>   	return 0;
>   }
>   
> +static int gsc_fw_is_loaded(struct xe_gt *gt)
> +{
> +	return xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)) &
> +			      HECI1_FWSTS1_INIT_COMPLETE;
> +}
This function is duplicated exactly in the GSC source file. That seems 
bad. Either it should be exported and shared or the usage here should be 
moved to the GSC specific file.

John.

> +
> +static void wa_14015076503_start(struct xe_gt *gt)
> +{
> +	/* WA only applies if the GSC is loaded */
> +	if (!XE_WA(gt, 14015076503) || !gsc_fw_is_loaded(gt))
> +		return;
> +
> +	/*
> +	 * wa_14015076503: if the GSC FW is loaded, we need to alert it that
> +	 * we're going to do a GSC engine reset and then wait for 200ms for the
> +	 * FW to get ready for it.
> +	 */
> +	xe_mmio_rmw32(gt, HECI_H_GS1(MTL_GSC_HECI2_BASE),
> +		      0, HECI_H_GS1_ER_PREP);
> +
> +	/* make sure the reset bit is clear when writing the CSR reg */
> +	xe_mmio_rmw32(gt, HECI_H_CSR(MTL_GSC_HECI2_BASE),
> +		      HECI_H_CSR_RST, HECI_H_CSR_IG);
> +	msleep(200);
> +
> +	return;
> +}
> +
> +static void
> +wa_14015076503_end(struct xe_gt *gt)
> +{
> +	if (!XE_WA(gt, 14015076503))
> +		return;
> +
> +	xe_mmio_rmw32(gt, HECI_H_GS1(MTL_GSC_HECI2_BASE),
> +		      HECI_H_GS1_ER_PREP, 0);
> +}
> +
>   static int do_gt_reset(struct xe_gt *gt)
>   {
>   	int err;
>   
> +	wa_14015076503_start(gt);
> +
>   	xe_mmio_write32(gt, GDRST, GRDOM_FULL);
>   	err = xe_mmio_wait32(gt, GDRST, GRDOM_FULL, 0, 5000, NULL, false);
>   	if (err)
>   		xe_gt_err(gt, "failed to clear GEN11_GRDOM_FULL (%pe)\n",
>   			  ERR_PTR(err));
>   
> +	wa_14015076503_end(gt);
> +
>   	return err;
>   }
>   
> diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules
> index f3ff774dc4aa..132c35497f74 100644
> --- a/drivers/gpu/drm/xe/xe_wa_oob.rules
> +++ b/drivers/gpu/drm/xe/xe_wa_oob.rules
> @@ -19,3 +19,4 @@
>   		SUBPLATFORM(DG2, G12)
>   16017236439	PLATFORM(PVC)
>   22010954014	PLATFORM(DG2)
> +14015076503	MEDIA_VERSION(1300)


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

* Re: [Intel-xe] [PATCH 06/12] drm/xe/gsc: GSC FW load
  2023-11-08 22:17   ` John Harrison
@ 2023-11-08 22:23     ` Daniele Ceraolo Spurio
  2023-11-08 22:29       ` John Harrison
  0 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-08 22:23 UTC (permalink / raw)
  To: John Harrison, intel-xe



On 11/8/2023 2:17 PM, John Harrison wrote:
> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>> The GSC FW must be copied in a 4MB stolen memory allocation, whose GGTT
>> address is then passed as a parameter to a dedicated load instruction
>> submitted via the GSC engine.
>>
>> Since the GSC load is relatively slow (up to 250ms), we perform it
>> asynchronously via a worker. This requires us to make sure that the
>> worker has stopped before suspending/unloading.
>>
>> Note that we can't yet use xe_migrate_copy for the copy because it
>> doesn't work with stolen memory right now, so we do a memcpy from the
>> CPU side instead.
>>
>> Bspec: 65306, 65346
>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>> Cc: John Harrison <John.C.Harrison@Intel.com>
>> ---
>>   .../gpu/drm/xe/instructions/xe_gsc_commands.h |  34 +++
>>   .../gpu/drm/xe/instructions/xe_instr_defs.h   |   1 +
>>   drivers/gpu/drm/xe/regs/xe_gsc_regs.h         |  29 +++
>>   drivers/gpu/drm/xe/xe_gsc.c                   | 240 ++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_gsc.h                   |   3 +
>>   drivers/gpu/drm/xe/xe_gsc_types.h             |  17 ++
>>   drivers/gpu/drm/xe/xe_uc.c                    |  12 +-
>>   7 files changed, 335 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>>   create mode 100644 drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>>
>> diff --git a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h 
>> b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>> new file mode 100644
>> index 000000000000..c7a833d7f965
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>> @@ -0,0 +1,34 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2023 Intel Corporation
>> + */
>> +
>> +#ifndef _XE_GSC_COMMANDS_H_
>> +#define _XE_GSC_COMMANDS_H_
>> +
>> +#include "instructions/xe_instr_defs.h"
>> +
>> +/*
>> + * All GSCCS-specific commands have fixed length, so we can include 
>> it in the
>> + * defines. Note that the generic GSC command header structure 
>> includes an
>> + * optional data field in bits 9-21, but there are no commands that 
>> actually use
>> + * it; some of the commands are instead defined as having an 
>> extended length
>> + * field spanning bits 0-15, even if the extra bits are not required 
>> because the
>> + * longest GSCCS command is only 8 dwords. To handle this, the 
>> defines below use
>> + * a single field for both data and len. If we ever get a commands 
>> that does
>> + * actually have data and this approach doesn't work for it we can 
>> re-work it
>> + * at that point.
>> + */
>> +
>> +#define GSC_OPCODE        REG_GENMASK(28, 22)
>> +#define GSC_CMD_DATA_AND_LEN    REG_GENMASK(21, 0)
>> +
>> +#define __GSC_INSTR(op, dl) \
>> +    (XE_INSTR_GSC | \
>> +    REG_FIELD_PREP(GSC_OPCODE, op) | \
>> +    REG_FIELD_PREP(GSC_CMD_DATA_AND_LEN, dl))
>> +
>> +#define GSC_FW_LOAD __GSC_INSTR(1, 2)
>> +#define   GSC_FW_LOAD_LIMIT_VALID REG_BIT(31)
>> +
>> +#endif
>> diff --git a/drivers/gpu/drm/xe/instructions/xe_instr_defs.h 
>> b/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
>> index e403b4fcc20a..04179b2a48e1 100644
>> --- a/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
>> +++ b/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
>> @@ -15,6 +15,7 @@
>>    */
>>   #define XE_INSTR_CMD_TYPE        GENMASK(31, 29)
>>   #define   XE_INSTR_MI REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x0)
>> +#define   XE_INSTR_GSC REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x2)
>>   #define   XE_INSTR_GFXPIPE REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x3)
>>     /*
>> diff --git a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h 
>> b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>> new file mode 100644
>> index 000000000000..22d2ad9cb64d
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>> @@ -0,0 +1,29 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2023 Intel Corporation
>> + */
>> +
>> +#ifndef _XE_GSC_REGS_H_
>> +#define _XE_GSC_REGS_H_
>> +
>> +#include <linux/compiler.h>
>> +#include <linux/types.h>
>> +
>> +#include "regs/xe_reg_defs.h"
>> +
>> +/* Definitions of GSC H/W registers, bits, etc */
>> +
>> +#define MTL_GSC_HECI1_BASE    0x00116000
>> +#define MTL_GSC_HECI2_BASE    0x00117000
>> +
>> +/*
>> + * The FWSTS register values are FW defined and can be different 
>> between
>> + * HECI1 and HECI2
>> + */
>> +#define HECI_FWSTS1(base)                XE_REG((base) + 0xc40)
>> +#define   HECI1_FWSTS1_CURRENT_STATE            REG_GENMASK(3, 0)
>> +#define   HECI1_FWSTS1_CURRENT_STATE_RESET        0
>> +#define   HECI1_FWSTS1_PROXY_STATE_NORMAL        5
>> +#define   HECI1_FWSTS1_INIT_COMPLETE            REG_BIT(9)
>> +
>> +#endif
>> diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
>> index 3f709577d73b..7e5ba9039163 100644
>> --- a/drivers/gpu/drm/xe/xe_gsc.c
>> +++ b/drivers/gpu/drm/xe/xe_gsc.c
>> @@ -5,10 +5,20 @@
>>     #include "xe_gsc.h"
>>   +#include <drm/drm_managed.h>
>> +
>> +#include "xe_bb.h"
>> +#include "xe_bo.h"
>>   #include "xe_device.h"
>> +#include "xe_exec_queue.h"
>>   #include "xe_gt.h"
>>   #include "xe_gt_printk.h"
>> +#include "xe_map.h"
>> +#include "xe_mmio.h"
>> +#include "xe_sched_job.h"
>>   #include "xe_uc_fw.h"
>> +#include "instructions/xe_gsc_commands.h"
>> +#include "regs/xe_gsc_regs.h"
>>     static struct xe_gt *
>>   gsc_to_gt(struct xe_gsc *gsc)
>> @@ -16,6 +26,134 @@ gsc_to_gt(struct xe_gsc *gsc)
>>       return container_of(gsc, struct xe_gt, uc.gsc);
>>   }
>>   +static int memcpy_fw(struct xe_gsc *gsc)
>> +{
>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>> +    struct xe_device *xe = gt_to_xe(gt);
>> +    u32 fw_size = gsc->fw.size;
>> +    void *storage;
>> +
>> +    /*
>> +     * FIXME: xe_migrate_copy does not work with stolen mem yet, so 
>> we use
>> +     * a memcpy for now.
>> +     */
>> +    storage = kmalloc(fw_size, GFP_KERNEL);
>> +    if (!storage)
>> +        return -ENOMEM;
>> +
>> +    xe_map_memcpy_from(xe, storage, &gsc->fw.bo->vmap, 0, fw_size);
>> +    xe_map_memcpy_to(xe, &gsc->private->vmap, 0, storage, fw_size);
>> +    xe_map_memset(xe, &gsc->private->vmap, fw_size, 0, 
>> gsc->private->size - fw_size);
>> +
>> +    kfree(storage);
>> +
>> +    return 0;
>> +}
>> +
>> +static int emit_gsc_upload(struct xe_gsc *gsc)
>> +{
>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>> +    u32 offset = xe_bo_ggtt_addr(gsc->private);
>> +    struct xe_bb *bb;
>> +    struct xe_sched_job *job;
>> +    struct dma_fence *fence;
>> +    long timeout;
>> +
>> +    bb = xe_bb_new(gt, 4, false);
>> +    if (IS_ERR(bb))
>> +        return PTR_ERR(bb);
>> +
>> +    bb->cs[bb->len++] = GSC_FW_LOAD;
>> +    bb->cs[bb->len++] = lower_32_bits(offset);
>> +    bb->cs[bb->len++] = upper_32_bits(offset);
>> +    bb->cs[bb->len++] = (gsc->private->size / SZ_4K) | 
>> GSC_FW_LOAD_LIMIT_VALID;
>> +
>> +    job = xe_bb_create_job(gsc->q, bb);
>> +    if (IS_ERR(job)) {
>> +        xe_bb_free(bb, NULL);
>> +        return PTR_ERR(job);
>> +    }
>> +
>> +    xe_sched_job_arm(job);
>> +    fence = dma_fence_get(&job->drm.s_fence->finished);
>> +    xe_sched_job_push(job);
>> +
>> +    timeout = dma_fence_wait_timeout(fence, false, HZ);
>> +    dma_fence_put(fence);
>> +    xe_bb_free(bb, NULL);
>> +    if (timeout < 0)
>> +        return timeout;
>> +    else if (!timeout)
>> +        return -ETIME;
>> +
>> +    return 0;
>> +}
>> +
>> +static int gsc_fw_is_loaded(struct xe_gt *gt)
>> +{
>> +    return xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)) &
>> +                  HECI1_FWSTS1_INIT_COMPLETE;
>> +}
>> +
>> +static int gsc_fw_wait(struct xe_gt *gt)
>> +{
>> +    return xe_mmio_wait32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE),
>> +                  HECI1_FWSTS1_INIT_COMPLETE,
>> +                  HECI1_FWSTS1_INIT_COMPLETE,
>> +                  500, NULL, false);
> The 500 at least needs a comment to explain where it comes from and 
> why. If not a #define as well.
>
> I assume this is the <=250ms in the commit description?
>

yup,  I just doubled the 250 to 500 to give it a bit of wiggle room. 
I'll add a comment.

>> +}
>> +
>> +static int gsc_upload(struct xe_gsc *gsc)
>> +{
>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>> +    int err;
>> +
>> +    if (XE_WARN_ON(!xe_uc_fw_is_loadable(&gsc->fw) || !gsc->q || 
>> gsc_fw_is_loaded(gt)))
> The last term here is a register read of a firmware written value? The 
> kernel should not barf with WARNs and such due to external data. Those 
> are for internal bugs only. Dodgy external data should just be an 
> xe_gt_err, shouldn't it?

The idea was that we shouldn't be here if the GSC HW reports that we've 
already loaded, we should have bailed early (in xe_gsc_load_start), so 
somewhere in the stack we have a programming bug.

>
>> +        return 0;
> And returning zero means the state will transition to TRANSFERRED not 
> LOAD_FAIL. That seems plausible in the case of already loaded, but in 
> the other cases that seems wrong?

You're right, will fix.

Daniele

>
> John.
>
>> +
>> +    err = memcpy_fw(gsc);
>> +    if (err) {
>> +        xe_gt_err(gt, "Failed to memcpy GSC FW\n");
>> +        return err;
>> +    }
>> +
>> +    err = emit_gsc_upload(gsc);
>> +    if (err) {
>> +        xe_gt_err(gt, "Failed to emit GSC FW upload (%pe)\n", 
>> ERR_PTR(err));
>> +        return err;
>> +    }
>> +
>> +    err = gsc_fw_wait(gt);
>> +    if (err) {
>> +        xe_gt_err(gt, "Failed to wait for GSC load (%pe)\n", 
>> ERR_PTR(err));
>> +        return err;
>> +    }
>> +
>> +    xe_gt_dbg(gt, "GSC FW async load completed\n");
>> +
>> +    return 0;
>> +}
>> +
>> +static void gsc_work(struct work_struct *work)
>> +{
>> +    struct xe_gsc *gsc = container_of(work, typeof(*gsc), work);
>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>> +    struct xe_device *xe = gt_to_xe(gt);
>> +    int ret;
>> +
>> +    xe_device_mem_access_get(xe);
>> +    xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC);
>> +
>> +    ret = gsc_upload(gsc);
>> +    if (ret)
>> +        xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_LOAD_FAIL);
>> +    else
>> +        xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
>> +
>> +    xe_force_wake_put(gt_to_fw(gt), XE_FW_GSC);
>> +    xe_device_mem_access_put(xe);
>> +}
>> +
>>   int xe_gsc_init(struct xe_gsc *gsc)
>>   {
>>       struct xe_gt *gt = gsc_to_gt(gsc);
>> @@ -23,6 +161,7 @@ int xe_gsc_init(struct xe_gsc *gsc)
>>       int ret;
>>         gsc->fw.type = XE_UC_FW_TYPE_GSC;
>> +    INIT_WORK(&gsc->work, gsc_work);
>>         /* The GSC uC is only available on the media GT */
>>       if (tile->media_gt && (gt != tile->media_gt)) {
>> @@ -48,3 +187,104 @@ int xe_gsc_init(struct xe_gsc *gsc)
>>       return ret;
>>   }
>>   +static void free_resources(struct drm_device *drm, void *arg)
>> +{
>> +    struct xe_gsc *gsc = arg;
>> +
>> +    if (gsc->wq) {
>> +        destroy_workqueue(gsc->wq);
>> +        gsc->wq = NULL;
>> +    }
>> +
>> +    if (gsc->q) {
>> +        xe_exec_queue_put(gsc->q);
>> +        gsc->q = NULL;
>> +    }
>> +
>> +    if (gsc->private) {
>> +        xe_bo_unpin_map_no_vm(gsc->private);
>> +        gsc->private = NULL;
>> +    }
>> +}
>> +
>> +int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc)
>> +{
>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>> +    struct xe_tile *tile = gt_to_tile(gt);
>> +    struct xe_device *xe = gt_to_xe(gt);
>> +    struct xe_hw_engine *hwe = xe_gt_hw_engine(gt, 
>> XE_ENGINE_CLASS_OTHER, 0, true);
>> +    struct xe_exec_queue *q;
>> +    struct workqueue_struct *wq;
>> +    struct xe_bo *bo;
>> +    int err;
>> +
>> +    if (!xe_uc_fw_is_available(&gsc->fw))
>> +        return 0;
>> +
>> +    if (!hwe)
>> +        return -ENODEV;
>> +
>> +    bo = xe_bo_create_pin_map(xe, tile, NULL, SZ_4M,
>> +                  ttm_bo_type_kernel,
>> +                  XE_BO_CREATE_STOLEN_BIT |
>> +                  XE_BO_CREATE_GGTT_BIT);
>> +    if (IS_ERR(bo))
>> +        return PTR_ERR(bo);
>> +
>> +    q = xe_exec_queue_create(xe, NULL,
>> +                 BIT(hwe->logical_instance), 1, hwe,
>> +                 EXEC_QUEUE_FLAG_KERNEL |
>> +                 EXEC_QUEUE_FLAG_PERMANENT);
>> +    if (IS_ERR(q)) {
>> +        xe_gt_err(gt, "Failed to create queue for GSC submission\n");
>> +        err = PTR_ERR(q);
>> +        goto out_bo;
>> +    }
>> +
>> +    wq = alloc_ordered_workqueue("gsc-ordered-wq", 0);
>> +    if (!wq) {
>> +        err = -ENOMEM;
>> +        goto out_q;
>> +    }
>> +
>> +    gsc->private = bo;
>> +    gsc->q = q;
>> +    gsc->wq = wq;
>> +
>> +    err = drmm_add_action_or_reset(&xe->drm, free_resources, gsc);
>> +    if (err)
>> +        return err;
>> +
>> +    xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_LOADABLE);
>> +
>> +    return 0;
>> +
>> +out_q:
>> +    xe_exec_queue_put(q);
>> +out_bo:
>> +    xe_bo_unpin_map_no_vm(bo);
>> +    return err;
>> +
>> +}
>> +
>> +void xe_gsc_load_start(struct xe_gsc *gsc)
>> +{
>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>> +
>> +    if (!xe_uc_fw_is_loadable(&gsc->fw) || !gsc->q)
>> +        return;
>> +
>> +    /* GSC FW survives GT reset and D3Hot */
>> +    if (gsc_fw_is_loaded(gt)) {
>> +        xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
>> +        return;
>> +    }
>> +
>> +    queue_work(gsc->wq, &gsc->work);
>> +}
>> +
>> +void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc)
>> +{
>> +    if (xe_uc_fw_is_loadable(&gsc->fw) && gsc->wq)
>> +        flush_work(&gsc->work);
>> +}
>> diff --git a/drivers/gpu/drm/xe/xe_gsc.h b/drivers/gpu/drm/xe/xe_gsc.h
>> index baa7f21f4204..f870eddc77d4 100644
>> --- a/drivers/gpu/drm/xe/xe_gsc.h
>> +++ b/drivers/gpu/drm/xe/xe_gsc.h
>> @@ -9,5 +9,8 @@
>>   #include "xe_gsc_types.h"
>>     int xe_gsc_init(struct xe_gsc *gsc);
>> +int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc);
>> +void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc);
>> +void xe_gsc_load_start(struct xe_gsc *gsc);
>>     #endif
>> diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h 
>> b/drivers/gpu/drm/xe/xe_gsc_types.h
>> index 1bc50583fe58..57fefd66a7ea 100644
>> --- a/drivers/gpu/drm/xe/xe_gsc_types.h
>> +++ b/drivers/gpu/drm/xe/xe_gsc_types.h
>> @@ -6,8 +6,13 @@
>>   #ifndef _XE_GSC_TYPES_H_
>>   #define _XE_GSC_TYPES_H_
>>   +#include <linux/workqueue.h>
>> +
>>   #include "xe_uc_fw_types.h"
>>   +struct xe_bo;
>> +struct xe_exec_queue;
>> +
>>   /**
>>    * struct xe_gsc - GSC
>>    */
>> @@ -17,6 +22,18 @@ struct xe_gsc {
>>         /** @security_version: SVN found in the fetched blob */
>>       u32 security_version;
>> +
>> +    /** @private: Private data for use by the GSC FW */
>> +    struct xe_bo *private;
>> +
>> +    /** @q: Default queue used for submissions to GSC FW */
>> +    struct xe_exec_queue *q;
>> +
>> +    /** @wq: workqueue to handle jobs for delayed load and proxy 
>> handling */
>> +    struct workqueue_struct *wq;
>> +
>> +    /** @work: delayed load and proxy handling work */
>> +    struct work_struct work;
>>   };
>>     #endif
>> diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
>> index b67154c78dff..15dcd1f91e9c 100644
>> --- a/drivers/gpu/drm/xe/xe_uc.c
>> +++ b/drivers/gpu/drm/xe/xe_uc.c
>> @@ -74,11 +74,17 @@ int xe_uc_init(struct xe_uc *uc)
>>    */
>>   int xe_uc_init_post_hwconfig(struct xe_uc *uc)
>>   {
>> +    int err;
>> +
>>       /* GuC submission not enabled, nothing to do */
>>       if (!xe_device_uc_enabled(uc_to_xe(uc)))
>>           return 0;
>>   -    return xe_guc_init_post_hwconfig(&uc->guc);
>> +    err = xe_guc_init_post_hwconfig(&uc->guc);
>> +    if (err)
>> +        return err;
>> +
>> +    return xe_gsc_init_post_hwconfig(&uc->gsc);
>>   }
>>     static int uc_reset(struct xe_uc *uc)
>> @@ -173,6 +179,9 @@ int xe_uc_init_hw(struct xe_uc *uc)
>>       ret = xe_huc_auth(&uc->huc);
>>       xe_gt_assert(uc_to_gt(uc), !ret);
>>   +    /* GSC load is async */
>> +    xe_gsc_load_start(&uc->gsc);
>> +
>>       return 0;
>>   }
>>   @@ -197,6 +206,7 @@ void xe_uc_gucrc_disable(struct xe_uc *uc)
>>     void xe_uc_stop_prepare(struct xe_uc *uc)
>>   {
>> +    xe_gsc_wait_for_worker_completion(&uc->gsc);
>>       xe_guc_stop_prepare(&uc->guc);
>>   }
>


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

* Re: [Intel-xe] [PATCH 08/12] drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload
  2023-10-27 22:29 ` [Intel-xe] [PATCH 08/12] drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload Daniele Ceraolo Spurio
@ 2023-11-08 22:24   ` John Harrison
  0 siblings, 0 replies; 56+ messages in thread
From: John Harrison @ 2023-11-08 22:24 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> GSC is only killed by an FLR, so we need to trigger one on unload to
> make sure we stop it. This is because we assign a chunk of memory to
> the GSC as part of the FW load, so we need to make sure it stops
> using it when we release it to the system on driver unload. Note that
> this is not a problem of the unload per-se, because the GSC will not
> touch that memory unless there are requests for it coming from the
> driver; therefore, no accesses will happen while Xe is not loaded,
> but if we re-load the driver then the GSC might wake up and try to
> access that old memory location again.
>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Reviewed-by: John Harrison <John.C.Harrison@Intel.com>

> ---
>   drivers/gpu/drm/xe/xe_gsc.c | 18 ++++++++++++++++++
>   1 file changed, 18 insertions(+)
>
> diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
> index 7e5ba9039163..edf74780322a 100644
> --- a/drivers/gpu/drm/xe/xe_gsc.c
> +++ b/drivers/gpu/drm/xe/xe_gsc.c
> @@ -106,6 +106,7 @@ static int gsc_fw_wait(struct xe_gt *gt)
>   static int gsc_upload(struct xe_gsc *gsc)
>   {
>   	struct xe_gt *gt = gsc_to_gt(gsc);
> +	struct xe_device *xe = gt_to_xe(gt);
>   	int err;
>   
>   	if (XE_WARN_ON(!xe_uc_fw_is_loadable(&gsc->fw) || !gsc->q || gsc_fw_is_loaded(gt)))
> @@ -117,6 +118,23 @@ static int gsc_upload(struct xe_gsc *gsc)
>   		return err;
>   	}
>   
> +	/*
> +	 * GSC is only killed by an FLR, so we need to trigger one on unload to
> +	 * make sure we stop it. This is because we assign a chunk of memory to
> +	 * the GSC as part of the FW load, so we need to make sure it stops
> +	 * using it when we release it to the system on driver unload. Note that
> +	 * this is not a problem of the unload per-se, because the GSC will not
> +	 * touch that memory unless there are requests for it coming from the
> +	 * driver; therefore, no accesses will happen while Xe is not loaded,
> +	 * but if we re-load the driver then the GSC might wake up and try to
> +	 * access that old memory location again.
> +	 * Given that an FLR is a very disruptive action (see the FLR function
> +	 * for details), we want to do it as the last action before releasing
> +	 * the access to the MMIO bar, which means we need to do it as part of
> +	 * mmio cleanup.
> +	 */
> +	xe->needs_flr_on_fini = true;
> +
>   	err = emit_gsc_upload(gsc);
>   	if (err) {
>   		xe_gt_err(gt, "Failed to emit GSC FW upload (%pe)\n", ERR_PTR(err));


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

* Re: [Intel-xe] [PATCH 06/12] drm/xe/gsc: GSC FW load
  2023-11-08 22:23     ` Daniele Ceraolo Spurio
@ 2023-11-08 22:29       ` John Harrison
  0 siblings, 0 replies; 56+ messages in thread
From: John Harrison @ 2023-11-08 22:29 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 11/8/2023 14:23, Daniele Ceraolo Spurio wrote:
> On 11/8/2023 2:17 PM, John Harrison wrote:
>> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>>> The GSC FW must be copied in a 4MB stolen memory allocation, whose GGTT
>>> address is then passed as a parameter to a dedicated load instruction
>>> submitted via the GSC engine.
>>>
>>> Since the GSC load is relatively slow (up to 250ms), we perform it
>>> asynchronously via a worker. This requires us to make sure that the
>>> worker has stopped before suspending/unloading.
>>>
>>> Note that we can't yet use xe_migrate_copy for the copy because it
>>> doesn't work with stolen memory right now, so we do a memcpy from the
>>> CPU side instead.
>>>
>>> Bspec: 65306, 65346
>>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>>> Cc: John Harrison <John.C.Harrison@Intel.com>
>>> ---
>>>   .../gpu/drm/xe/instructions/xe_gsc_commands.h |  34 +++
>>>   .../gpu/drm/xe/instructions/xe_instr_defs.h   |   1 +
>>>   drivers/gpu/drm/xe/regs/xe_gsc_regs.h         |  29 +++
>>>   drivers/gpu/drm/xe/xe_gsc.c                   | 240 
>>> ++++++++++++++++++
>>>   drivers/gpu/drm/xe/xe_gsc.h                   |   3 +
>>>   drivers/gpu/drm/xe/xe_gsc_types.h             |  17 ++
>>>   drivers/gpu/drm/xe/xe_uc.c                    |  12 +-
>>>   7 files changed, 335 insertions(+), 1 deletion(-)
>>>   create mode 100644 drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>>>   create mode 100644 drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>>>
>>> diff --git a/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h 
>>> b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>>> new file mode 100644
>>> index 000000000000..c7a833d7f965
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>>> @@ -0,0 +1,34 @@
>>> +/* SPDX-License-Identifier: MIT */
>>> +/*
>>> + * Copyright © 2023 Intel Corporation
>>> + */
>>> +
>>> +#ifndef _XE_GSC_COMMANDS_H_
>>> +#define _XE_GSC_COMMANDS_H_
>>> +
>>> +#include "instructions/xe_instr_defs.h"
>>> +
>>> +/*
>>> + * All GSCCS-specific commands have fixed length, so we can include 
>>> it in the
>>> + * defines. Note that the generic GSC command header structure 
>>> includes an
>>> + * optional data field in bits 9-21, but there are no commands that 
>>> actually use
>>> + * it; some of the commands are instead defined as having an 
>>> extended length
>>> + * field spanning bits 0-15, even if the extra bits are not 
>>> required because the
>>> + * longest GSCCS command is only 8 dwords. To handle this, the 
>>> defines below use
>>> + * a single field for both data and len. If we ever get a commands 
>>> that does
>>> + * actually have data and this approach doesn't work for it we can 
>>> re-work it
>>> + * at that point.
>>> + */
>>> +
>>> +#define GSC_OPCODE        REG_GENMASK(28, 22)
>>> +#define GSC_CMD_DATA_AND_LEN    REG_GENMASK(21, 0)
>>> +
>>> +#define __GSC_INSTR(op, dl) \
>>> +    (XE_INSTR_GSC | \
>>> +    REG_FIELD_PREP(GSC_OPCODE, op) | \
>>> +    REG_FIELD_PREP(GSC_CMD_DATA_AND_LEN, dl))
>>> +
>>> +#define GSC_FW_LOAD __GSC_INSTR(1, 2)
>>> +#define   GSC_FW_LOAD_LIMIT_VALID REG_BIT(31)
>>> +
>>> +#endif
>>> diff --git a/drivers/gpu/drm/xe/instructions/xe_instr_defs.h 
>>> b/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
>>> index e403b4fcc20a..04179b2a48e1 100644
>>> --- a/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
>>> +++ b/drivers/gpu/drm/xe/instructions/xe_instr_defs.h
>>> @@ -15,6 +15,7 @@
>>>    */
>>>   #define XE_INSTR_CMD_TYPE        GENMASK(31, 29)
>>>   #define   XE_INSTR_MI REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x0)
>>> +#define   XE_INSTR_GSC REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x2)
>>>   #define   XE_INSTR_GFXPIPE REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x3)
>>>     /*
>>> diff --git a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h 
>>> b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>>> new file mode 100644
>>> index 000000000000..22d2ad9cb64d
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>>> @@ -0,0 +1,29 @@
>>> +/* SPDX-License-Identifier: MIT */
>>> +/*
>>> + * Copyright © 2023 Intel Corporation
>>> + */
>>> +
>>> +#ifndef _XE_GSC_REGS_H_
>>> +#define _XE_GSC_REGS_H_
>>> +
>>> +#include <linux/compiler.h>
>>> +#include <linux/types.h>
>>> +
>>> +#include "regs/xe_reg_defs.h"
>>> +
>>> +/* Definitions of GSC H/W registers, bits, etc */
>>> +
>>> +#define MTL_GSC_HECI1_BASE    0x00116000
>>> +#define MTL_GSC_HECI2_BASE    0x00117000
>>> +
>>> +/*
>>> + * The FWSTS register values are FW defined and can be different 
>>> between
>>> + * HECI1 and HECI2
>>> + */
>>> +#define HECI_FWSTS1(base)                XE_REG((base) + 0xc40)
>>> +#define   HECI1_FWSTS1_CURRENT_STATE REG_GENMASK(3, 0)
>>> +#define   HECI1_FWSTS1_CURRENT_STATE_RESET        0
>>> +#define   HECI1_FWSTS1_PROXY_STATE_NORMAL        5
>>> +#define   HECI1_FWSTS1_INIT_COMPLETE            REG_BIT(9)
>>> +
>>> +#endif
>>> diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
>>> index 3f709577d73b..7e5ba9039163 100644
>>> --- a/drivers/gpu/drm/xe/xe_gsc.c
>>> +++ b/drivers/gpu/drm/xe/xe_gsc.c
>>> @@ -5,10 +5,20 @@
>>>     #include "xe_gsc.h"
>>>   +#include <drm/drm_managed.h>
>>> +
>>> +#include "xe_bb.h"
>>> +#include "xe_bo.h"
>>>   #include "xe_device.h"
>>> +#include "xe_exec_queue.h"
>>>   #include "xe_gt.h"
>>>   #include "xe_gt_printk.h"
>>> +#include "xe_map.h"
>>> +#include "xe_mmio.h"
>>> +#include "xe_sched_job.h"
>>>   #include "xe_uc_fw.h"
>>> +#include "instructions/xe_gsc_commands.h"
>>> +#include "regs/xe_gsc_regs.h"
>>>     static struct xe_gt *
>>>   gsc_to_gt(struct xe_gsc *gsc)
>>> @@ -16,6 +26,134 @@ gsc_to_gt(struct xe_gsc *gsc)
>>>       return container_of(gsc, struct xe_gt, uc.gsc);
>>>   }
>>>   +static int memcpy_fw(struct xe_gsc *gsc)
>>> +{
>>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>>> +    struct xe_device *xe = gt_to_xe(gt);
>>> +    u32 fw_size = gsc->fw.size;
>>> +    void *storage;
>>> +
>>> +    /*
>>> +     * FIXME: xe_migrate_copy does not work with stolen mem yet, so 
>>> we use
>>> +     * a memcpy for now.
>>> +     */
>>> +    storage = kmalloc(fw_size, GFP_KERNEL);
>>> +    if (!storage)
>>> +        return -ENOMEM;
>>> +
>>> +    xe_map_memcpy_from(xe, storage, &gsc->fw.bo->vmap, 0, fw_size);
>>> +    xe_map_memcpy_to(xe, &gsc->private->vmap, 0, storage, fw_size);
>>> +    xe_map_memset(xe, &gsc->private->vmap, fw_size, 0, 
>>> gsc->private->size - fw_size);
>>> +
>>> +    kfree(storage);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int emit_gsc_upload(struct xe_gsc *gsc)
>>> +{
>>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>>> +    u32 offset = xe_bo_ggtt_addr(gsc->private);
>>> +    struct xe_bb *bb;
>>> +    struct xe_sched_job *job;
>>> +    struct dma_fence *fence;
>>> +    long timeout;
>>> +
>>> +    bb = xe_bb_new(gt, 4, false);
>>> +    if (IS_ERR(bb))
>>> +        return PTR_ERR(bb);
>>> +
>>> +    bb->cs[bb->len++] = GSC_FW_LOAD;
>>> +    bb->cs[bb->len++] = lower_32_bits(offset);
>>> +    bb->cs[bb->len++] = upper_32_bits(offset);
>>> +    bb->cs[bb->len++] = (gsc->private->size / SZ_4K) | 
>>> GSC_FW_LOAD_LIMIT_VALID;
>>> +
>>> +    job = xe_bb_create_job(gsc->q, bb);
>>> +    if (IS_ERR(job)) {
>>> +        xe_bb_free(bb, NULL);
>>> +        return PTR_ERR(job);
>>> +    }
>>> +
>>> +    xe_sched_job_arm(job);
>>> +    fence = dma_fence_get(&job->drm.s_fence->finished);
>>> +    xe_sched_job_push(job);
>>> +
>>> +    timeout = dma_fence_wait_timeout(fence, false, HZ);
>>> +    dma_fence_put(fence);
>>> +    xe_bb_free(bb, NULL);
>>> +    if (timeout < 0)
>>> +        return timeout;
>>> +    else if (!timeout)
>>> +        return -ETIME;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int gsc_fw_is_loaded(struct xe_gt *gt)
>>> +{
>>> +    return xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)) &
>>> +                  HECI1_FWSTS1_INIT_COMPLETE;
>>> +}
>>> +
>>> +static int gsc_fw_wait(struct xe_gt *gt)
>>> +{
>>> +    return xe_mmio_wait32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE),
>>> +                  HECI1_FWSTS1_INIT_COMPLETE,
>>> +                  HECI1_FWSTS1_INIT_COMPLETE,
>>> +                  500, NULL, false);
>> The 500 at least needs a comment to explain where it comes from and 
>> why. If not a #define as well.
>>
>> I assume this is the <=250ms in the commit description?
>>
>
> yup,  I just doubled the 250 to 500 to give it a bit of wiggle room. 
> I'll add a comment.
>
>>> +}
>>> +
>>> +static int gsc_upload(struct xe_gsc *gsc)
>>> +{
>>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>>> +    int err;
>>> +
>>> +    if (XE_WARN_ON(!xe_uc_fw_is_loadable(&gsc->fw) || !gsc->q || 
>>> gsc_fw_is_loaded(gt)))
>> The last term here is a register read of a firmware written value? 
>> The kernel should not barf with WARNs and such due to external data. 
>> Those are for internal bugs only. Dodgy external data should just be 
>> an xe_gt_err, shouldn't it?
>
> The idea was that we shouldn't be here if the GSC HW reports that 
> we've already loaded, we should have bailed early (in 
> xe_gsc_load_start), so somewhere in the stack we have a programming bug.
Right but once you include external inputs, that programming bug might 
not be in the KMD. The KMD is perfect and never goes wrong, but we don't 
trust those pesky hardware designers ;).

If nothing else, you could get a PCIe drop-out between the previous 
check and this one. So all the software state is perfect but the 
hardware is toast. That should not be a WARN, it should be a xe_gt_err.

John.

>
>>
>>> +        return 0;
>> And returning zero means the state will transition to TRANSFERRED not 
>> LOAD_FAIL. That seems plausible in the case of already loaded, but in 
>> the other cases that seems wrong?
>
> You're right, will fix.
>
> Daniele
>
>>
>> John.
>>
>>> +
>>> +    err = memcpy_fw(gsc);
>>> +    if (err) {
>>> +        xe_gt_err(gt, "Failed to memcpy GSC FW\n");
>>> +        return err;
>>> +    }
>>> +
>>> +    err = emit_gsc_upload(gsc);
>>> +    if (err) {
>>> +        xe_gt_err(gt, "Failed to emit GSC FW upload (%pe)\n", 
>>> ERR_PTR(err));
>>> +        return err;
>>> +    }
>>> +
>>> +    err = gsc_fw_wait(gt);
>>> +    if (err) {
>>> +        xe_gt_err(gt, "Failed to wait for GSC load (%pe)\n", 
>>> ERR_PTR(err));
>>> +        return err;
>>> +    }
>>> +
>>> +    xe_gt_dbg(gt, "GSC FW async load completed\n");
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static void gsc_work(struct work_struct *work)
>>> +{
>>> +    struct xe_gsc *gsc = container_of(work, typeof(*gsc), work);
>>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>>> +    struct xe_device *xe = gt_to_xe(gt);
>>> +    int ret;
>>> +
>>> +    xe_device_mem_access_get(xe);
>>> +    xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC);
>>> +
>>> +    ret = gsc_upload(gsc);
>>> +    if (ret)
>>> +        xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_LOAD_FAIL);
>>> +    else
>>> +        xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
>>> +
>>> +    xe_force_wake_put(gt_to_fw(gt), XE_FW_GSC);
>>> +    xe_device_mem_access_put(xe);
>>> +}
>>> +
>>>   int xe_gsc_init(struct xe_gsc *gsc)
>>>   {
>>>       struct xe_gt *gt = gsc_to_gt(gsc);
>>> @@ -23,6 +161,7 @@ int xe_gsc_init(struct xe_gsc *gsc)
>>>       int ret;
>>>         gsc->fw.type = XE_UC_FW_TYPE_GSC;
>>> +    INIT_WORK(&gsc->work, gsc_work);
>>>         /* The GSC uC is only available on the media GT */
>>>       if (tile->media_gt && (gt != tile->media_gt)) {
>>> @@ -48,3 +187,104 @@ int xe_gsc_init(struct xe_gsc *gsc)
>>>       return ret;
>>>   }
>>>   +static void free_resources(struct drm_device *drm, void *arg)
>>> +{
>>> +    struct xe_gsc *gsc = arg;
>>> +
>>> +    if (gsc->wq) {
>>> +        destroy_workqueue(gsc->wq);
>>> +        gsc->wq = NULL;
>>> +    }
>>> +
>>> +    if (gsc->q) {
>>> +        xe_exec_queue_put(gsc->q);
>>> +        gsc->q = NULL;
>>> +    }
>>> +
>>> +    if (gsc->private) {
>>> +        xe_bo_unpin_map_no_vm(gsc->private);
>>> +        gsc->private = NULL;
>>> +    }
>>> +}
>>> +
>>> +int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc)
>>> +{
>>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>>> +    struct xe_tile *tile = gt_to_tile(gt);
>>> +    struct xe_device *xe = gt_to_xe(gt);
>>> +    struct xe_hw_engine *hwe = xe_gt_hw_engine(gt, 
>>> XE_ENGINE_CLASS_OTHER, 0, true);
>>> +    struct xe_exec_queue *q;
>>> +    struct workqueue_struct *wq;
>>> +    struct xe_bo *bo;
>>> +    int err;
>>> +
>>> +    if (!xe_uc_fw_is_available(&gsc->fw))
>>> +        return 0;
>>> +
>>> +    if (!hwe)
>>> +        return -ENODEV;
>>> +
>>> +    bo = xe_bo_create_pin_map(xe, tile, NULL, SZ_4M,
>>> +                  ttm_bo_type_kernel,
>>> +                  XE_BO_CREATE_STOLEN_BIT |
>>> +                  XE_BO_CREATE_GGTT_BIT);
>>> +    if (IS_ERR(bo))
>>> +        return PTR_ERR(bo);
>>> +
>>> +    q = xe_exec_queue_create(xe, NULL,
>>> +                 BIT(hwe->logical_instance), 1, hwe,
>>> +                 EXEC_QUEUE_FLAG_KERNEL |
>>> +                 EXEC_QUEUE_FLAG_PERMANENT);
>>> +    if (IS_ERR(q)) {
>>> +        xe_gt_err(gt, "Failed to create queue for GSC submission\n");
>>> +        err = PTR_ERR(q);
>>> +        goto out_bo;
>>> +    }
>>> +
>>> +    wq = alloc_ordered_workqueue("gsc-ordered-wq", 0);
>>> +    if (!wq) {
>>> +        err = -ENOMEM;
>>> +        goto out_q;
>>> +    }
>>> +
>>> +    gsc->private = bo;
>>> +    gsc->q = q;
>>> +    gsc->wq = wq;
>>> +
>>> +    err = drmm_add_action_or_reset(&xe->drm, free_resources, gsc);
>>> +    if (err)
>>> +        return err;
>>> +
>>> +    xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_LOADABLE);
>>> +
>>> +    return 0;
>>> +
>>> +out_q:
>>> +    xe_exec_queue_put(q);
>>> +out_bo:
>>> +    xe_bo_unpin_map_no_vm(bo);
>>> +    return err;
>>> +
>>> +}
>>> +
>>> +void xe_gsc_load_start(struct xe_gsc *gsc)
>>> +{
>>> +    struct xe_gt *gt = gsc_to_gt(gsc);
>>> +
>>> +    if (!xe_uc_fw_is_loadable(&gsc->fw) || !gsc->q)
>>> +        return;
>>> +
>>> +    /* GSC FW survives GT reset and D3Hot */
>>> +    if (gsc_fw_is_loaded(gt)) {
>>> +        xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
>>> +        return;
>>> +    }
>>> +
>>> +    queue_work(gsc->wq, &gsc->work);
>>> +}
>>> +
>>> +void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc)
>>> +{
>>> +    if (xe_uc_fw_is_loadable(&gsc->fw) && gsc->wq)
>>> +        flush_work(&gsc->work);
>>> +}
>>> diff --git a/drivers/gpu/drm/xe/xe_gsc.h b/drivers/gpu/drm/xe/xe_gsc.h
>>> index baa7f21f4204..f870eddc77d4 100644
>>> --- a/drivers/gpu/drm/xe/xe_gsc.h
>>> +++ b/drivers/gpu/drm/xe/xe_gsc.h
>>> @@ -9,5 +9,8 @@
>>>   #include "xe_gsc_types.h"
>>>     int xe_gsc_init(struct xe_gsc *gsc);
>>> +int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc);
>>> +void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc);
>>> +void xe_gsc_load_start(struct xe_gsc *gsc);
>>>     #endif
>>> diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h 
>>> b/drivers/gpu/drm/xe/xe_gsc_types.h
>>> index 1bc50583fe58..57fefd66a7ea 100644
>>> --- a/drivers/gpu/drm/xe/xe_gsc_types.h
>>> +++ b/drivers/gpu/drm/xe/xe_gsc_types.h
>>> @@ -6,8 +6,13 @@
>>>   #ifndef _XE_GSC_TYPES_H_
>>>   #define _XE_GSC_TYPES_H_
>>>   +#include <linux/workqueue.h>
>>> +
>>>   #include "xe_uc_fw_types.h"
>>>   +struct xe_bo;
>>> +struct xe_exec_queue;
>>> +
>>>   /**
>>>    * struct xe_gsc - GSC
>>>    */
>>> @@ -17,6 +22,18 @@ struct xe_gsc {
>>>         /** @security_version: SVN found in the fetched blob */
>>>       u32 security_version;
>>> +
>>> +    /** @private: Private data for use by the GSC FW */
>>> +    struct xe_bo *private;
>>> +
>>> +    /** @q: Default queue used for submissions to GSC FW */
>>> +    struct xe_exec_queue *q;
>>> +
>>> +    /** @wq: workqueue to handle jobs for delayed load and proxy 
>>> handling */
>>> +    struct workqueue_struct *wq;
>>> +
>>> +    /** @work: delayed load and proxy handling work */
>>> +    struct work_struct work;
>>>   };
>>>     #endif
>>> diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
>>> index b67154c78dff..15dcd1f91e9c 100644
>>> --- a/drivers/gpu/drm/xe/xe_uc.c
>>> +++ b/drivers/gpu/drm/xe/xe_uc.c
>>> @@ -74,11 +74,17 @@ int xe_uc_init(struct xe_uc *uc)
>>>    */
>>>   int xe_uc_init_post_hwconfig(struct xe_uc *uc)
>>>   {
>>> +    int err;
>>> +
>>>       /* GuC submission not enabled, nothing to do */
>>>       if (!xe_device_uc_enabled(uc_to_xe(uc)))
>>>           return 0;
>>>   -    return xe_guc_init_post_hwconfig(&uc->guc);
>>> +    err = xe_guc_init_post_hwconfig(&uc->guc);
>>> +    if (err)
>>> +        return err;
>>> +
>>> +    return xe_gsc_init_post_hwconfig(&uc->gsc);
>>>   }
>>>     static int uc_reset(struct xe_uc *uc)
>>> @@ -173,6 +179,9 @@ int xe_uc_init_hw(struct xe_uc *uc)
>>>       ret = xe_huc_auth(&uc->huc);
>>>       xe_gt_assert(uc_to_gt(uc), !ret);
>>>   +    /* GSC load is async */
>>> +    xe_gsc_load_start(&uc->gsc);
>>> +
>>>       return 0;
>>>   }
>>>   @@ -197,6 +206,7 @@ void xe_uc_gucrc_disable(struct xe_uc *uc)
>>>     void xe_uc_stop_prepare(struct xe_uc *uc)
>>>   {
>>> +    xe_gsc_wait_for_worker_completion(&uc->gsc);
>>>       xe_guc_stop_prepare(&uc->guc);
>>>   }
>>
>


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

* Re: [Intel-xe] [PATCH 07/12] drm/xe/gsc: Implement WA 14015076503
  2023-11-08 22:22   ` John Harrison
@ 2023-11-08 22:35     ` Daniele Ceraolo Spurio
  2023-11-08 22:40       ` John Harrison
  0 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-08 22:35 UTC (permalink / raw)
  To: John Harrison, intel-xe



On 11/8/2023 2:22 PM, John Harrison wrote:
> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>> When the GSC FW is loaded, we need to inform it when a GSCCS reset is
>> coming and then wait 200ms for it to get ready to process the reset.
>>
>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> Cc: John Harrison <john.c.harrison@intel.com>
>> ---
>>   drivers/gpu/drm/xe/Makefile           |  2 +-
>>   drivers/gpu/drm/xe/regs/xe_gsc_regs.h | 10 ++++++
>>   drivers/gpu/drm/xe/xe_gt.c            | 44 +++++++++++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_wa_oob.rules    |  1 +
>>   4 files changed, 56 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
>> index 474b6044d054..4a442dcf4d79 100644
>> --- a/drivers/gpu/drm/xe/Makefile
>> +++ b/drivers/gpu/drm/xe/Makefile
>> @@ -37,7 +37,7 @@ quiet_cmd_wa_oob = GEN     $(notdir $(generated_oob))
>>   $(generated_oob) &: $(obj)/xe_gen_wa_oob 
>> $(srctree)/$(src)/xe_wa_oob.rules
>>       $(call cmd,wa_oob)
>>   -$(obj)/xe_guc.o $(obj)/xe_migrate.o $(obj)/xe_ring_ops.o 
>> $(obj)/xe_vm.o $(obj)/xe_wa.o: $(generated_oob)
>> +$(obj)/xe_gt.o $(obj)/xe_guc.o $(obj)/xe_migrate.o 
>> $(obj)/xe_ring_ops.o $(obj)/xe_vm.o $(obj)/xe_wa.o: $(generated_oob)
> Is it not worth splitting this into multiple lines?

Not sure how readable it'd be if we have a rule on multiple lines. Maybe 
instead I can just add a variable with the list of files and use that in 
the rule. Not sure it belongs in this patch (or series) though.

>
>>     # Please keep these build lists sorted!
>>   diff --git a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h 
>> b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>> index 22d2ad9cb64d..9a84b55d66ee 100644
>> --- a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>> +++ b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>> @@ -16,6 +16,13 @@
>>   #define MTL_GSC_HECI1_BASE    0x00116000
>>   #define MTL_GSC_HECI2_BASE    0x00117000
>>   +#define HECI_H_CSR(base)    XE_REG((base) + 0x4)
>> +#define   HECI_H_CSR_IE        REG_BIT(0)
>> +#define   HECI_H_CSR_IS        REG_BIT(1)
>> +#define   HECI_H_CSR_IG        REG_BIT(2)
>> +#define   HECI_H_CSR_RDY    REG_BIT(3)
>> +#define   HECI_H_CSR_RST    REG_BIT(4)
>> +
>>   /*
>>    * The FWSTS register values are FW defined and can be different 
>> between
>>    * HECI1 and HECI2
>> @@ -26,4 +33,7 @@
>>   #define   HECI1_FWSTS1_PROXY_STATE_NORMAL        5
>>   #define   HECI1_FWSTS1_INIT_COMPLETE            REG_BIT(9)
>>   +#define HECI_H_GS1(base)    XE_REG((base) + 0xc4c)
>> +#define   HECI_H_GS1_ER_PREP    REG_BIT(0)
>> +
>>   #endif
>> diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
>> index 73c090762771..0e8e24bded1c 100644
>> --- a/drivers/gpu/drm/xe/xe_gt.c
>> +++ b/drivers/gpu/drm/xe/xe_gt.c
>> @@ -10,8 +10,10 @@
>>   #include <drm/drm_managed.h>
>>   #include <drm/xe_drm.h>
>>   +#include "generated/xe_wa_oob.h"
>>   #include "instructions/xe_gfxpipe_commands.h"
>>   #include "instructions/xe_mi_commands.h"
>> +#include "regs/xe_gsc_regs.h"
>>   #include "regs/xe_gt_regs.h"
>>   #include "xe_assert.h"
>>   #include "xe_bb.h"
>> @@ -504,16 +506,58 @@ int xe_gt_init(struct xe_gt *gt)
>>       return 0;
>>   }
>>   +static int gsc_fw_is_loaded(struct xe_gt *gt)
>> +{
>> +    return xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)) &
>> +                  HECI1_FWSTS1_INIT_COMPLETE;
>> +}
> This function is duplicated exactly in the GSC source file. That seems 
> bad. Either it should be exported and shared or the usage here should 
> be moved to the GSC specific file.

This was on purpose. We do have a bit of duplication for simpler 
functions in the Xe codebase; e.g., guc_to_gt() is re-implemented in 
every single file that uses it (I count 6 copies). I can see that this 
is pushing it a bit tough, since it's a GSC internal detail in a non-GSC 
file, so I'll export it as you suggested. I might also instead export 
the WA code from the GSC file to hide all the GSC internals in there, 
will look at both options and see what looks better.

Daniele

>
> John.
>
>> +
>> +static void wa_14015076503_start(struct xe_gt *gt)
>> +{
>> +    /* WA only applies if the GSC is loaded */
>> +    if (!XE_WA(gt, 14015076503) || !gsc_fw_is_loaded(gt))
>> +        return;
>> +
>> +    /*
>> +     * wa_14015076503: if the GSC FW is loaded, we need to alert it 
>> that
>> +     * we're going to do a GSC engine reset and then wait for 200ms 
>> for the
>> +     * FW to get ready for it.
>> +     */
>> +    xe_mmio_rmw32(gt, HECI_H_GS1(MTL_GSC_HECI2_BASE),
>> +              0, HECI_H_GS1_ER_PREP);
>> +
>> +    /* make sure the reset bit is clear when writing the CSR reg */
>> +    xe_mmio_rmw32(gt, HECI_H_CSR(MTL_GSC_HECI2_BASE),
>> +              HECI_H_CSR_RST, HECI_H_CSR_IG);
>> +    msleep(200);
>> +
>> +    return;
>> +}
>> +
>> +static void
>> +wa_14015076503_end(struct xe_gt *gt)
>> +{
>> +    if (!XE_WA(gt, 14015076503))
>> +        return;
>> +
>> +    xe_mmio_rmw32(gt, HECI_H_GS1(MTL_GSC_HECI2_BASE),
>> +              HECI_H_GS1_ER_PREP, 0);
>> +}
>> +
>>   static int do_gt_reset(struct xe_gt *gt)
>>   {
>>       int err;
>>   +    wa_14015076503_start(gt);
>> +
>>       xe_mmio_write32(gt, GDRST, GRDOM_FULL);
>>       err = xe_mmio_wait32(gt, GDRST, GRDOM_FULL, 0, 5000, NULL, false);
>>       if (err)
>>           xe_gt_err(gt, "failed to clear GEN11_GRDOM_FULL (%pe)\n",
>>                 ERR_PTR(err));
>>   +    wa_14015076503_end(gt);
>> +
>>       return err;
>>   }
>>   diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules 
>> b/drivers/gpu/drm/xe/xe_wa_oob.rules
>> index f3ff774dc4aa..132c35497f74 100644
>> --- a/drivers/gpu/drm/xe/xe_wa_oob.rules
>> +++ b/drivers/gpu/drm/xe/xe_wa_oob.rules
>> @@ -19,3 +19,4 @@
>>           SUBPLATFORM(DG2, G12)
>>   16017236439    PLATFORM(PVC)
>>   22010954014    PLATFORM(DG2)
>> +14015076503    MEDIA_VERSION(1300)
>


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

* Re: [Intel-xe] [PATCH 07/12] drm/xe/gsc: Implement WA 14015076503
  2023-11-08 22:35     ` Daniele Ceraolo Spurio
@ 2023-11-08 22:40       ` John Harrison
  0 siblings, 0 replies; 56+ messages in thread
From: John Harrison @ 2023-11-08 22:40 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 11/8/2023 14:35, Daniele Ceraolo Spurio wrote:
> On 11/8/2023 2:22 PM, John Harrison wrote:
>> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>>> When the GSC FW is loaded, we need to inform it when a GSCCS reset is
>>> coming and then wait 200ms for it to get ready to process the reset.
>>>
>>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>>> Cc: John Harrison <john.c.harrison@intel.com>
>>> ---
>>>   drivers/gpu/drm/xe/Makefile           |  2 +-
>>>   drivers/gpu/drm/xe/regs/xe_gsc_regs.h | 10 ++++++
>>>   drivers/gpu/drm/xe/xe_gt.c            | 44 
>>> +++++++++++++++++++++++++++
>>>   drivers/gpu/drm/xe/xe_wa_oob.rules    |  1 +
>>>   4 files changed, 56 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
>>> index 474b6044d054..4a442dcf4d79 100644
>>> --- a/drivers/gpu/drm/xe/Makefile
>>> +++ b/drivers/gpu/drm/xe/Makefile
>>> @@ -37,7 +37,7 @@ quiet_cmd_wa_oob = GEN     $(notdir $(generated_oob))
>>>   $(generated_oob) &: $(obj)/xe_gen_wa_oob 
>>> $(srctree)/$(src)/xe_wa_oob.rules
>>>       $(call cmd,wa_oob)
>>>   -$(obj)/xe_guc.o $(obj)/xe_migrate.o $(obj)/xe_ring_ops.o 
>>> $(obj)/xe_vm.o $(obj)/xe_wa.o: $(generated_oob)
>>> +$(obj)/xe_gt.o $(obj)/xe_guc.o $(obj)/xe_migrate.o 
>>> $(obj)/xe_ring_ops.o $(obj)/xe_vm.o $(obj)/xe_wa.o: $(generated_oob)
>> Is it not worth splitting this into multiple lines?
>
> Not sure how readable it'd be if we have a rule on multiple lines. 
> Maybe instead I can just add a variable with the list of files and use 
> that in the rule. Not sure it belongs in this patch (or series) though.
Yeah, I guess.

>
>>
>>>     # Please keep these build lists sorted!
>>>   diff --git a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h 
>>> b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>>> index 22d2ad9cb64d..9a84b55d66ee 100644
>>> --- a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>>> +++ b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>>> @@ -16,6 +16,13 @@
>>>   #define MTL_GSC_HECI1_BASE    0x00116000
>>>   #define MTL_GSC_HECI2_BASE    0x00117000
>>>   +#define HECI_H_CSR(base)    XE_REG((base) + 0x4)
>>> +#define   HECI_H_CSR_IE        REG_BIT(0)
>>> +#define   HECI_H_CSR_IS        REG_BIT(1)
>>> +#define   HECI_H_CSR_IG        REG_BIT(2)
>>> +#define   HECI_H_CSR_RDY    REG_BIT(3)
>>> +#define   HECI_H_CSR_RST    REG_BIT(4)
>>> +
>>>   /*
>>>    * The FWSTS register values are FW defined and can be different 
>>> between
>>>    * HECI1 and HECI2
>>> @@ -26,4 +33,7 @@
>>>   #define   HECI1_FWSTS1_PROXY_STATE_NORMAL        5
>>>   #define   HECI1_FWSTS1_INIT_COMPLETE            REG_BIT(9)
>>>   +#define HECI_H_GS1(base)    XE_REG((base) + 0xc4c)
>>> +#define   HECI_H_GS1_ER_PREP    REG_BIT(0)
>>> +
>>>   #endif
>>> diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
>>> index 73c090762771..0e8e24bded1c 100644
>>> --- a/drivers/gpu/drm/xe/xe_gt.c
>>> +++ b/drivers/gpu/drm/xe/xe_gt.c
>>> @@ -10,8 +10,10 @@
>>>   #include <drm/drm_managed.h>
>>>   #include <drm/xe_drm.h>
>>>   +#include "generated/xe_wa_oob.h"
>>>   #include "instructions/xe_gfxpipe_commands.h"
>>>   #include "instructions/xe_mi_commands.h"
>>> +#include "regs/xe_gsc_regs.h"
>>>   #include "regs/xe_gt_regs.h"
>>>   #include "xe_assert.h"
>>>   #include "xe_bb.h"
>>> @@ -504,16 +506,58 @@ int xe_gt_init(struct xe_gt *gt)
>>>       return 0;
>>>   }
>>>   +static int gsc_fw_is_loaded(struct xe_gt *gt)
>>> +{
>>> +    return xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)) &
>>> +                  HECI1_FWSTS1_INIT_COMPLETE;
>>> +}
>> This function is duplicated exactly in the GSC source file. That 
>> seems bad. Either it should be exported and shared or the usage here 
>> should be moved to the GSC specific file.
>
> This was on purpose. We do have a bit of duplication for simpler 
> functions in the Xe codebase; e.g., guc_to_gt() is re-implemented in 
> every single file that uses it (I count 6 copies). I can see that this 
> is pushing it a bit tough, since it's a GSC internal detail in a non-
Seriously? Ew! Surely that has to be worth an xe_guc_accessor.h or 
something!

> GSC file, so I'll export it as you suggested. I might also instead 
> export the WA code from the GSC file to hide all the GSC internals in 
> there, will look at both options and see what looks better.

Keeping all the GSC internals in the GSC file seems better to me. Given 
that this is all firmware specific 'registers' rather than bspec defined 
hardware registers. But either way works.

John.


>
> Daniele
>
>>
>> John.
>>
>>> +
>>> +static void wa_14015076503_start(struct xe_gt *gt)
>>> +{
>>> +    /* WA only applies if the GSC is loaded */
>>> +    if (!XE_WA(gt, 14015076503) || !gsc_fw_is_loaded(gt))
>>> +        return;
>>> +
>>> +    /*
>>> +     * wa_14015076503: if the GSC FW is loaded, we need to alert it 
>>> that
>>> +     * we're going to do a GSC engine reset and then wait for 200ms 
>>> for the
>>> +     * FW to get ready for it.
>>> +     */
>>> +    xe_mmio_rmw32(gt, HECI_H_GS1(MTL_GSC_HECI2_BASE),
>>> +              0, HECI_H_GS1_ER_PREP);
>>> +
>>> +    /* make sure the reset bit is clear when writing the CSR reg */
>>> +    xe_mmio_rmw32(gt, HECI_H_CSR(MTL_GSC_HECI2_BASE),
>>> +              HECI_H_CSR_RST, HECI_H_CSR_IG);
>>> +    msleep(200);
>>> +
>>> +    return;
>>> +}
>>> +
>>> +static void
>>> +wa_14015076503_end(struct xe_gt *gt)
>>> +{
>>> +    if (!XE_WA(gt, 14015076503))
>>> +        return;
>>> +
>>> +    xe_mmio_rmw32(gt, HECI_H_GS1(MTL_GSC_HECI2_BASE),
>>> +              HECI_H_GS1_ER_PREP, 0);
>>> +}
>>> +
>>>   static int do_gt_reset(struct xe_gt *gt)
>>>   {
>>>       int err;
>>>   +    wa_14015076503_start(gt);
>>> +
>>>       xe_mmio_write32(gt, GDRST, GRDOM_FULL);
>>>       err = xe_mmio_wait32(gt, GDRST, GRDOM_FULL, 0, 5000, NULL, 
>>> false);
>>>       if (err)
>>>           xe_gt_err(gt, "failed to clear GEN11_GRDOM_FULL (%pe)\n",
>>>                 ERR_PTR(err));
>>>   +    wa_14015076503_end(gt);
>>> +
>>>       return err;
>>>   }
>>>   diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules 
>>> b/drivers/gpu/drm/xe/xe_wa_oob.rules
>>> index f3ff774dc4aa..132c35497f74 100644
>>> --- a/drivers/gpu/drm/xe/xe_wa_oob.rules
>>> +++ b/drivers/gpu/drm/xe/xe_wa_oob.rules
>>> @@ -19,3 +19,4 @@
>>>           SUBPLATFORM(DG2, G12)
>>>   16017236439    PLATFORM(PVC)
>>>   22010954014    PLATFORM(DG2)
>>> +14015076503    MEDIA_VERSION(1300)
>>
>


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

* Re: [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware
  2023-11-07 23:38       ` John Harrison
@ 2023-11-09 19:59         ` Daniele Ceraolo Spurio
  0 siblings, 0 replies; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-09 19:59 UTC (permalink / raw)
  To: John Harrison, intel-xe



On 11/7/2023 3:38 PM, John Harrison wrote:
> On 11/7/2023 15:24, Daniele Ceraolo Spurio wrote:
>> On 11/7/2023 3:07 PM, John Harrison wrote:
>>> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>>>> Major GuC versions greater than 70 will have the submission version in
>>>> the herader irrespective of their minor version number.
>>>>
>>>> Signed-off-by: Daniele Ceraolo Spurio 
>>>> <daniele.ceraolospurio@intel.com>
>>>> Cc: Matthew Brost <matthew.brost@intel.com>
>>>> Cc: John Harrison <John.C.Harrison@Intel.com>
>>>> Reviewed-by: Matthew Brost <matthew.brost@intel.com>
>>>> ---
>>>>   drivers/gpu/drm/xe/xe_uc_fw.c | 2 +-
>>>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c 
>>>> b/drivers/gpu/drm/xe/xe_uc_fw.c
>>>> index 3032c4f148d4..91d4a2272ee7 100644
>>>> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
>>>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
>>>> @@ -278,7 +278,7 @@ static void guc_read_css_info(struct xe_uc_fw 
>>>> *uc_fw, struct uc_css_header *css)
>>>>       xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);
>>>>       xe_gt_assert(gt, uc_fw->major_ver_found >= 70);
>>>>   -    if (uc_fw->minor_ver_found >= 6) {
>>>> +    if (uc_fw->major_ver_found > 70 || uc_fw->minor_ver_found >= 6) {
>>> I strongly recommend that we update to a newer version than 70.5.x 
>>> for all platforms and then just drop all this code before Xe goes 
>>> live. There is no need to be carrying this legacy hack in the shiny 
>>> new clean driver!
>>
>> How do you guarantee that the user is running at least 70.6? They 
>> might have an old firmware package. We don't currently fail if the 
>> minor is too low, we just throw a warning, so the driver would still 
>> load but the compatibility would be left unset in that scenario. Or 
>> are you suggesting to just fail the load if GuC < 70.6 ?
> The only publicly supported platforms for Xe right now are LNL and 
> later, aren't they? There is no GuC prior to 70.6 for LNL or later. 
> And anything else is unofficial and for internal testing only.
>
> But yeah, maybe go with >=70.6 or fail (it currently says >=70.0.0 or 
> fail?) to be totally safe.

I went to implement this, but I've realized that the newest GuC FW we 
have pushed for DG1 is 70.5.1, so forcing 70.6 would break DG1 support. 
I think the best option here would be to just pull DG1 support from Xe 
since we're not validating it, instead of pushing a newer GuC for a 
platform that's not fully supported.
TODO list has been updated, but in the meantime I'll stick with this 
patch for the GSC series.

Daniele

>
> John.
>
>>
>> Daniele
>>
>>>
>>> John.
>>>
>>>>           /* v70.6.0 adds CSS header support */
>>>>           guc->submission_state.version.major =
>>>>               FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
>>>
>>
>


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

* Re: [Intel-xe] [PATCH 00/12] GSC FW loading
  2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
                   ` (14 preceding siblings ...)
  2023-10-27 22:33 ` [Intel-xe] ✗ CI.KUnit: failure " Patchwork
@ 2023-11-13 16:05 ` Lucas De Marchi
  2023-11-13 16:09   ` Daniele Ceraolo Spurio
  15 siblings, 1 reply; 56+ messages in thread
From: Lucas De Marchi @ 2023-11-13 16:05 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio; +Cc: intel-xe

On Fri, Oct 27, 2023 at 03:29:14PM -0700, Daniele Ceraolo Spurio wrote:
>the GSC (Graphics Security Controller) is the root of trust for content
>protection operations (PXP, HDCP), so loading the the GSC FW is a
>prerequisite for those features. Loading the FW is required to turn off
>the GSC forcewake well (which we must turn on to enable GSCCS idleness)
>and therefore allows MC6 entry.

Regarding this last part, I wonder if we could simply put the GSC
forcewake if we detect the problematic situation: GSC fw not being
loaded and platform requiring that for proper MC6 entry.  Would that be
possible?

Lucas De Marchi


>
>The GSC FW uses 3 separate versions: release, compatibility and
>security. The compatibility version is the one that dictates whether the
>driver knows how to interface with the binary so that's the one we match
>against, but we also fetch the other two for debug information.
>
>The GSCCS is used to both load the FW (via the GSC_FW_LOAD command) and
>to send heci packets to it (via the GSC_HECI_PKT command).
>
>Note: the flr patch from Andrzej is being reviewed separately, I've just
>included it here because it is a dependency.
>
>Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>Cc: John Harrison <john.c.harrison@intel.com>
>
>Andrzej Hajda (1):
>  drm/xe: implement driver initiated function-reset
>
>Daniele Ceraolo Spurio (11):
>  fixup! drm/xe/guc: Report submission version of GuC firmware
>  drm/xe/uc: Rework uC version tracking
>  drm/xe/gsc: Introduce GSC FW
>  drm/xe/gsc: Parse GSC FW header
>  drm/xe/gsc: GSC FW load
>  drm/xe/gsc: Implement WA 14015076503
>  drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload
>  drm/xe/gsc: Add an interface for GSC packet submissions
>  drm/xe/gsc: Query GSC compatibility version
>  drm/xe/gsc: Define GSCCS for MTL
>  drm/xe/gsc: Define GSC FW for MTL
>
> drivers/gpu/drm/xe/Makefile                   |   4 +-
> .../gpu/drm/xe/abi/gsc_command_header_abi.h   |  46 +++
> .../gpu/drm/xe/abi/gsc_mkhi_commands_abi.h    |  39 ++
> .../gpu/drm/xe/instructions/xe_gsc_commands.h |  36 ++
> .../gpu/drm/xe/instructions/xe_instr_defs.h   |   1 +
> drivers/gpu/drm/xe/regs/xe_gsc_regs.h         |  39 ++
> drivers/gpu/drm/xe/regs/xe_regs.h             |   7 +
> drivers/gpu/drm/xe/xe_device.c                |  78 ++++
> drivers/gpu/drm/xe/xe_device_types.h          |   3 +
> drivers/gpu/drm/xe/xe_gsc.c                   | 389 ++++++++++++++++++
> drivers/gpu/drm/xe/xe_gsc.h                   |  16 +
> drivers/gpu/drm/xe/xe_gsc_submit.c            | 170 ++++++++
> drivers/gpu/drm/xe/xe_gsc_submit.h            |  30 ++
> drivers/gpu/drm/xe/xe_gsc_types.h             |  39 ++
> drivers/gpu/drm/xe/xe_gt.c                    |  46 +++
> drivers/gpu/drm/xe/xe_guc_types.h             |   9 -
> drivers/gpu/drm/xe/xe_hw_engine.c             |  20 +
> drivers/gpu/drm/xe/xe_module.c                |   5 +
> drivers/gpu/drm/xe/xe_module.h                |   1 +
> drivers/gpu/drm/xe/xe_pci.c                   |   2 +-
> drivers/gpu/drm/xe/xe_uc.c                    |  21 +-
> drivers/gpu/drm/xe/xe_uc_fw.c                 | 257 +++++++++---
> drivers/gpu/drm/xe/xe_uc_fw.h                 |   3 +
> drivers/gpu/drm/xe/xe_uc_fw_abi.h             | 113 +++++
> drivers/gpu/drm/xe/xe_uc_fw_types.h           |  40 +-
> drivers/gpu/drm/xe/xe_uc_types.h              |   3 +
> drivers/gpu/drm/xe/xe_wa_oob.rules            |   1 +
> 27 files changed, 1329 insertions(+), 89 deletions(-)
> create mode 100644 drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
> create mode 100644 drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h
> create mode 100644 drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
> create mode 100644 drivers/gpu/drm/xe/regs/xe_gsc_regs.h
> create mode 100644 drivers/gpu/drm/xe/xe_gsc.c
> create mode 100644 drivers/gpu/drm/xe/xe_gsc.h
> create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.c
> create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.h
> create mode 100644 drivers/gpu/drm/xe/xe_gsc_types.h
>
>-- 
>2.41.0
>

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

* Re: [Intel-xe] [PATCH 00/12] GSC FW loading
  2023-11-13 16:05 ` [Intel-xe] [PATCH 00/12] " Lucas De Marchi
@ 2023-11-13 16:09   ` Daniele Ceraolo Spurio
  0 siblings, 0 replies; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-13 16:09 UTC (permalink / raw)
  To: Lucas De Marchi; +Cc: intel-xe



On 11/13/2023 8:05 AM, Lucas De Marchi wrote:
> On Fri, Oct 27, 2023 at 03:29:14PM -0700, Daniele Ceraolo Spurio wrote:
>> the GSC (Graphics Security Controller) is the root of trust for content
>> protection operations (PXP, HDCP), so loading the the GSC FW is a
>> prerequisite for those features. Loading the FW is required to turn off
>> the GSC forcewake well (which we must turn on to enable GSCCS idleness)
>> and therefore allows MC6 entry.
>
> Regarding this last part, I wonder if we could simply put the GSC
> forcewake if we detect the problematic situation: GSC fw not being
> loaded and platform requiring that for proper MC6 entry.  Would that be
> possible?

No, the GSC ROM itself holds the forcewake ref and AFAIK the CPU can't 
directly touch anything ROM-related. When this first came up and we 
discussed it with HW architecture they said that the only option on MTL 
is to load the FW.

Daniele

>
> Lucas De Marchi
>
>
>>
>> The GSC FW uses 3 separate versions: release, compatibility and
>> security. The compatibility version is the one that dictates whether the
>> driver knows how to interface with the binary so that's the one we match
>> against, but we also fetch the other two for debug information.
>>
>> The GSCCS is used to both load the FW (via the GSC_FW_LOAD command) and
>> to send heci packets to it (via the GSC_HECI_PKT command).
>>
>> Note: the flr patch from Andrzej is being reviewed separately, I've just
>> included it here because it is a dependency.
>>
>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>> Cc: John Harrison <john.c.harrison@intel.com>
>>
>> Andrzej Hajda (1):
>>  drm/xe: implement driver initiated function-reset
>>
>> Daniele Ceraolo Spurio (11):
>>  fixup! drm/xe/guc: Report submission version of GuC firmware
>>  drm/xe/uc: Rework uC version tracking
>>  drm/xe/gsc: Introduce GSC FW
>>  drm/xe/gsc: Parse GSC FW header
>>  drm/xe/gsc: GSC FW load
>>  drm/xe/gsc: Implement WA 14015076503
>>  drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload
>>  drm/xe/gsc: Add an interface for GSC packet submissions
>>  drm/xe/gsc: Query GSC compatibility version
>>  drm/xe/gsc: Define GSCCS for MTL
>>  drm/xe/gsc: Define GSC FW for MTL
>>
>> drivers/gpu/drm/xe/Makefile                   |   4 +-
>> .../gpu/drm/xe/abi/gsc_command_header_abi.h   |  46 +++
>> .../gpu/drm/xe/abi/gsc_mkhi_commands_abi.h    |  39 ++
>> .../gpu/drm/xe/instructions/xe_gsc_commands.h |  36 ++
>> .../gpu/drm/xe/instructions/xe_instr_defs.h   |   1 +
>> drivers/gpu/drm/xe/regs/xe_gsc_regs.h         |  39 ++
>> drivers/gpu/drm/xe/regs/xe_regs.h             |   7 +
>> drivers/gpu/drm/xe/xe_device.c                |  78 ++++
>> drivers/gpu/drm/xe/xe_device_types.h          |   3 +
>> drivers/gpu/drm/xe/xe_gsc.c                   | 389 ++++++++++++++++++
>> drivers/gpu/drm/xe/xe_gsc.h                   |  16 +
>> drivers/gpu/drm/xe/xe_gsc_submit.c            | 170 ++++++++
>> drivers/gpu/drm/xe/xe_gsc_submit.h            |  30 ++
>> drivers/gpu/drm/xe/xe_gsc_types.h             |  39 ++
>> drivers/gpu/drm/xe/xe_gt.c                    |  46 +++
>> drivers/gpu/drm/xe/xe_guc_types.h             |   9 -
>> drivers/gpu/drm/xe/xe_hw_engine.c             |  20 +
>> drivers/gpu/drm/xe/xe_module.c                |   5 +
>> drivers/gpu/drm/xe/xe_module.h                |   1 +
>> drivers/gpu/drm/xe/xe_pci.c                   |   2 +-
>> drivers/gpu/drm/xe/xe_uc.c                    |  21 +-
>> drivers/gpu/drm/xe/xe_uc_fw.c                 | 257 +++++++++---
>> drivers/gpu/drm/xe/xe_uc_fw.h                 |   3 +
>> drivers/gpu/drm/xe/xe_uc_fw_abi.h             | 113 +++++
>> drivers/gpu/drm/xe/xe_uc_fw_types.h           |  40 +-
>> drivers/gpu/drm/xe/xe_uc_types.h              |   3 +
>> drivers/gpu/drm/xe/xe_wa_oob.rules            |   1 +
>> 27 files changed, 1329 insertions(+), 89 deletions(-)
>> create mode 100644 drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>> create mode 100644 drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h
>> create mode 100644 drivers/gpu/drm/xe/instructions/xe_gsc_commands.h
>> create mode 100644 drivers/gpu/drm/xe/regs/xe_gsc_regs.h
>> create mode 100644 drivers/gpu/drm/xe/xe_gsc.c
>> create mode 100644 drivers/gpu/drm/xe/xe_gsc.h
>> create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.c
>> create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.h
>> create mode 100644 drivers/gpu/drm/xe/xe_gsc_types.h
>>
>> -- 
>> 2.41.0
>>


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

* Re: [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions
  2023-10-27 22:29 ` [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions Daniele Ceraolo Spurio
  2023-10-31  8:08   ` Kandpal, Suraj
@ 2023-11-13 19:59   ` John Harrison
  2023-11-13 21:19     ` Daniele Ceraolo Spurio
  1 sibling, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-13 19:59 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> Communication with the GSC FW is done via input/output buffers, whose
> addresses are provided via a GSCCS command. The buffers contain a
> generic header and a client-specific packet (e.g. PXP, HDCP); the
> clients don't care about the header format and/or the GSCCS command in
> the batch, they only care about their client-specific header. This patch
> therefore introduces helpers that allow the callers to automatically
> fill in the input header, submit the GSCCS job and decode the output
> header, to make it so that the caller only needs to worry about their
> client-specific input and output messages.
>
> NOTE: this patch by itself only adds the interface so it does nothing,
> I've kept it separate for review but the plan is to squash it with the
> follow up patch before merge, so that the interface and the user are
> introduced at the same time.
>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
> Cc: Suraj Kandpal <suraj.kandpal@intel.com>
> ---
>   drivers/gpu/drm/xe/Makefile                   |   1 +
>   .../gpu/drm/xe/abi/gsc_command_header_abi.h   |  46 +++++
>   .../gpu/drm/xe/instructions/xe_gsc_commands.h |   2 +
>   drivers/gpu/drm/xe/xe_gsc_submit.c            | 170 ++++++++++++++++++
>   drivers/gpu/drm/xe/xe_gsc_submit.h            |  30 ++++
>   5 files changed, 249 insertions(+)
>   create mode 100644 drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.c
>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.h
>
> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
> index 4a442dcf4d79..876c122ad63c 100644
> --- a/drivers/gpu/drm/xe/Makefile
> +++ b/drivers/gpu/drm/xe/Makefile
> @@ -58,6 +58,7 @@ xe-y += xe_bb.o \
>   	xe_force_wake.o \
>   	xe_ggtt.o \
>   	xe_gsc.o \
> +	xe_gsc_submit.o \
>   	xe_gt.o \
>   	xe_gt_clock.o \
>   	xe_gt_debugfs.o \
> diff --git a/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
> new file mode 100644
> index 000000000000..a4c2646803b5
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
> @@ -0,0 +1,46 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef _ABI_GSC_COMMAND_HEADER_ABI_H
> +#define _ABI_GSC_COMMAND_HEADER_ABI_H
> +
> +#include <linux/types.h>
> +
> +struct intel_gsc_mtl_header {
Is this all really MTL platform specific? Or is it GSC version specific?

Given that the reset of the driver is moving to be IP version based 
instead of platform name based, it seems like this should also be based 
in some kind of version rather than platform name. Or are the GSC 
versions all just relative to the platform anyway?

Apart from that, it all looks good to me.

John.


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

* Re: [Intel-xe] [PATCH 10/12] drm/xe/gsc: Query GSC compatibility version
  2023-10-27 22:29 ` [Intel-xe] [PATCH 10/12] drm/xe/gsc: Query GSC compatibility version Daniele Ceraolo Spurio
@ 2023-11-13 20:10   ` John Harrison
  0 siblings, 0 replies; 56+ messages in thread
From: John Harrison @ 2023-11-13 20:10 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> The version is obtained via a dedicated MKHI GSC command.
> The compatibility version is what we want to match against for the GSC,
> so we need to call the FW version checker after obtaining the version.
>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
> ---
>   .../gpu/drm/xe/abi/gsc_mkhi_commands_abi.h    | 39 +++++++++
>   drivers/gpu/drm/xe/xe_gsc.c                   | 81 +++++++++++++++++++
>   drivers/gpu/drm/xe/xe_uc_fw.c                 | 18 +++--
>   drivers/gpu/drm/xe/xe_uc_fw.h                 |  1 +
>   4 files changed, 133 insertions(+), 6 deletions(-)
>   create mode 100644 drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h
>
> diff --git a/drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h b/drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h
> new file mode 100644
> index 000000000000..ad4d041873ab
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/abi/gsc_mkhi_commands_abi.h
> @@ -0,0 +1,39 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef _ABI_GSC_MKHI_COMMANDS_ABI_H
> +#define _ABI_GSC_MKHI_COMMANDS_ABI_H
> +
> +#include <linux/types.h>
> +
> +/* Heci client ID for MKHI commands */
> +#define HECI_MEADDRESS_MKHI 7
> +
> +/* Generic MKHI header */
> +struct gsc_mkhi_header {
> +	u8  group_id;
> +	u8  command;
> +	u8  reserved;
> +	u8  result;
> +} __packed;
> +
> +/* GFX_SRV commands */
> +#define MKHI_GROUP_ID_GFX_SRV 0x30
> +
> +#define MKHI_GFX_SRV_GET_HOST_COMPATIBILITY_VERSION (0x42)
> +
> +struct gsc_get_compatibility_version_in {
> +	struct gsc_mkhi_header header;
> +} __packed;
> +
> +struct gsc_get_compatibility_version_out {
> +	struct gsc_mkhi_header header;
> +	u16 proj_major;
> +	u16 compat_major;
> +	u16 compat_minor;
> +	u16 reserved[5];
> +} __packed;
> +
> +#endif
> diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
> index edf74780322a..63323a53f77f 100644
> --- a/drivers/gpu/drm/xe/xe_gsc.c
> +++ b/drivers/gpu/drm/xe/xe_gsc.c
> @@ -7,10 +7,12 @@
>   
>   #include <drm/drm_managed.h>
>   
> +#include "abi/gsc_mkhi_commands_abi.h"
>   #include "xe_bb.h"
>   #include "xe_bo.h"
>   #include "xe_device.h"
>   #include "xe_exec_queue.h"
> +#include "xe_gsc_submit.h"
>   #include "xe_gt.h"
>   #include "xe_gt_printk.h"
>   #include "xe_map.h"
> @@ -89,6 +91,77 @@ static int emit_gsc_upload(struct xe_gsc *gsc)
>   	return 0;
>   }
>   
> +#define query_msg_wr(xe_, map_, offset_, field_, val_) \
> +	xe_map_wr_field(xe_, map_, offset_, struct gsc_get_compatibility_version_in, field_, val_)
> +#define query_msg_rd(xe_, map_, offset_, field_) \
> +	xe_map_rd_field(xe_, map_, offset_, struct gsc_get_compatibility_version_out, field_)
These have a very generic 'query_msg' name but are very specifically 
tied to the compatibility version query command. That seems wrong.

Otherwise it seems good.

John.


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

* Re: [Intel-xe] [PATCH 11/12] drm/xe/gsc: Define GSCCS for MTL
  2023-10-27 22:29 ` [Intel-xe] [PATCH 11/12] drm/xe/gsc: Define GSCCS for MTL Daniele Ceraolo Spurio
@ 2023-11-13 20:23   ` John Harrison
  2023-11-13 21:32     ` Daniele Ceraolo Spurio
  0 siblings, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-13 20:23 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> Add the GSCCS to the media_xelpmp engine list. Note that since the
> GSCCS is only used with the GSC FW, we can consider it disabled if we
> don't have the FW available.
>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
> ---
>   drivers/gpu/drm/xe/xe_hw_engine.c | 20 ++++++++++++++++++++
>   drivers/gpu/drm/xe/xe_pci.c       |  2 +-
>   2 files changed, 21 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
> index b5b084590888..142783177e45 100644
> --- a/drivers/gpu/drm/xe/xe_hw_engine.c
> +++ b/drivers/gpu/drm/xe/xe_hw_engine.c
> @@ -26,6 +26,7 @@
>   #include "xe_rtp.h"
>   #include "xe_sched_job.h"
>   #include "xe_tuning.h"
> +#include "xe_uc_fw.h"
>   #include "xe_wa.h"
>   
>   #define MAX_MMIO_BASES 3
> @@ -610,6 +611,24 @@ static void read_compute_fuses(struct xe_gt *gt)
>   		read_compute_fuses_from_dss(gt);
>   }
>   
> +static void check_gsc_availability(struct xe_gt *gt)
> +{
> +	struct xe_device *xe = gt_to_xe(gt);
> +
> +	if (!(gt->info.engine_mask & BIT(XE_HW_ENGINE_GSCCS0)))
> +		return;
> +
> +	/*
> +	 * The GSCCS is only used to communicate with the GSC FW, so if we don't
> +	 * have the FW there is nothing we need the engine for and can therefore
> +	 * skip its initialization.
Is that correct? Is this testing against a firmware image being 
available on the system or against a firmware blob being defined for the 
platform?

If the firmware is not available but was defined then presumably that 
means that any feature that is reliant upon GSC is going to be broken - 
HDCP, PXP, etc. It seems like that should warrant more than a drm_info 
level message.

On the other hand, if the check is about whether a firmware blob is 
defined for this platform then surely this code path wouldn't even be 
taken in the first place? This can only be reached if actually trying to 
load a firmware file at all, can't it?

John.

> +	 */
> +	if (!xe_uc_fw_is_available(&gt->uc.gsc.fw)) {
> +		gt->info.engine_mask &= ~BIT(XE_HW_ENGINE_GSCCS0);
> +		drm_info(&xe->drm, "gsccs disabled due to lack of FW\n");
> +	}
> +}
> +
>   int xe_hw_engines_init_early(struct xe_gt *gt)
>   {
>   	int i;
> @@ -617,6 +636,7 @@ int xe_hw_engines_init_early(struct xe_gt *gt)
>   	read_media_fuses(gt);
>   	read_copy_fuses(gt);
>   	read_compute_fuses(gt);
> +	check_gsc_availability(gt);
>   
>   	BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT < XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN);
>   	BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT > XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX);
> diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
> index 2fae45b9d88e..c09b51735ee4 100644
> --- a/drivers/gpu/drm/xe/xe_pci.c
> +++ b/drivers/gpu/drm/xe/xe_pci.c
> @@ -197,7 +197,7 @@ static const struct xe_media_desc media_xelpmp = {
>   	.name = "Xe_LPM+",
>   	.hw_engine_mask =
>   		BIT(XE_HW_ENGINE_VCS0) | BIT(XE_HW_ENGINE_VCS2) |
> -		BIT(XE_HW_ENGINE_VECS0),	/* TODO: add GSC0 */
> +		BIT(XE_HW_ENGINE_VECS0) | BIT(XE_HW_ENGINE_GSCCS0)
>   };
>   
>   static const struct xe_media_desc media_xe2 = {


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

* Re: [Intel-xe] [PATCH 12/12] drm/xe/gsc: Define GSC FW for MTL
  2023-10-27 22:29 ` [Intel-xe] [PATCH 12/12] drm/xe/gsc: Define GSC FW " Daniele Ceraolo Spurio
@ 2023-11-13 20:26   ` John Harrison
  2023-11-13 21:33     ` Daniele Ceraolo Spurio
  0 siblings, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-13 20:26 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
> We track GSC FW based on its compatibility version, which is what
> determines the interface it supports.
> Also add a modparam override like the ones for GuC and HuC.
>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
> ---
>   drivers/gpu/drm/xe/xe_module.c |  5 +++++
>   drivers/gpu/drm/xe/xe_module.h |  1 +
>   drivers/gpu/drm/xe/xe_uc_fw.c  | 20 ++++++++++++--------
>   3 files changed, 18 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_module.c b/drivers/gpu/drm/xe/xe_module.c
> index 7194595e7f31..8df7aea64ad5 100644
> --- a/drivers/gpu/drm/xe/xe_module.c
> +++ b/drivers/gpu/drm/xe/xe_module.c
> @@ -41,6 +41,11 @@ module_param_named_unsafe(huc_firmware_path, xe_huc_firmware_path, charp, 0400);
>   MODULE_PARM_DESC(huc_firmware_path,
>   		 "HuC firmware path to use instead of the default one - empty string disables");
>   
> +char *xe_gsc_firmware_path;
> +module_param_named_unsafe(gsc_firmware_path, xe_gsc_firmware_path, charp, 0400);
> +MODULE_PARM_DESC(huc_firmware_path,
s/huc/gsc/;

John.

> +		 "GSC firmware path to use instead of the default one - empty string disables");
> +
>   char *xe_param_force_probe = CONFIG_DRM_XE_FORCE_PROBE;
>   module_param_named_unsafe(force_probe, xe_param_force_probe, charp, 0400);
>   MODULE_PARM_DESC(force_probe,
> diff --git a/drivers/gpu/drm/xe/xe_module.h b/drivers/gpu/drm/xe/xe_module.h
> index e1da1e9ca5cb..7f49f95630d5 100644
> --- a/drivers/gpu/drm/xe/xe_module.h
> +++ b/drivers/gpu/drm/xe/xe_module.h
> @@ -12,4 +12,5 @@ extern u32 xe_force_vram_bar_size;
>   extern int xe_guc_log_level;
>   extern char *xe_guc_firmware_path;
>   extern char *xe_huc_firmware_path;
> +extern char *xe_gsc_firmware_path;
>   extern char *xe_param_force_probe;
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
> index f57476f57de9..c9360d918b96 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
> @@ -121,6 +121,10 @@ struct fw_blobs_by_type {
>   	fw_def(ROCKETLAKE,	no_ver(i915,	huc,		tgl))		\
>   	fw_def(TIGERLAKE,	no_ver(i915,	huc,		tgl))
>   
> +/* for the GSC FW we match the compatibility version and not the release one */
> +#define XE_GSC_FIRMWARE_DEFS(fw_def, major_ver)		\
> +	fw_def(METEORLAKE,	major_ver(i915,	gsc,	mtl,	1, 0))
> +
>   #define MAKE_FW_PATH(dir__, uc__, shortname__, version__)			\
>   	__stringify(dir__) "/" __stringify(shortname__) "_" __stringify(uc__) version__ ".bin"
>   
> @@ -155,6 +159,7 @@ XE_GUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
>   		     fw_filename_mmp_ver, fw_filename_major_ver)
>   XE_HUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
>   		     fw_filename_mmp_ver, fw_filename_no_ver)
> +XE_GSC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE, fw_filename_major_ver)
>   
>   static struct xe_gt *
>   __uc_fw_to_gt(struct xe_uc_fw *uc_fw, enum xe_uc_fw_type type)
> @@ -196,23 +201,19 @@ uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw)
>   				     uc_fw_entry_mmp_ver,
>   				     uc_fw_entry_no_ver)
>   	};
> +	static const struct uc_fw_entry entries_gsc[] = {
> +		XE_GSC_FIRMWARE_DEFS(XE_UC_FW_ENTRY, uc_fw_entry_major_ver)
> +	};
>   	static const struct fw_blobs_by_type blobs_all[XE_UC_FW_NUM_TYPES] = {
>   		[XE_UC_FW_TYPE_GUC] = { entries_guc, ARRAY_SIZE(entries_guc) },
>   		[XE_UC_FW_TYPE_HUC] = { entries_huc, ARRAY_SIZE(entries_huc) },
> +		[XE_UC_FW_TYPE_GSC] = { entries_gsc, ARRAY_SIZE(entries_gsc) },
>   	};
>   	static const struct uc_fw_entry *entries;
>   	enum xe_platform p = xe->info.platform;
>   	u32 count;
>   	int i;
>   
> -	/*
> -	 * GSC FW support is still not fully in place, so we're not defining
> -	 * the FW blob yet because we don't want the driver to attempt to load
> -	 * it until we're ready for it.
> -	 */
> -	if (uc_fw->type == XE_UC_FW_TYPE_GSC)
> -		return;
> -
>   	xe_assert(xe, uc_fw->type < ARRAY_SIZE(blobs_all));
>   	entries = blobs_all[uc_fw->type].entries;
>   	count = blobs_all[uc_fw->type].count;
> @@ -248,6 +249,9 @@ uc_fw_override(struct xe_uc_fw *uc_fw)
>   	case XE_UC_FW_TYPE_HUC:
>   		path_override = xe_huc_firmware_path;
>   		break;
> +	case XE_UC_FW_TYPE_GSC:
> +		path_override = xe_gsc_firmware_path;
> +		break;
>   	default:
>   		break;
>   	}


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

* Re: [Intel-xe]  ✗ CI.checkpatch: warning for GSC FW loading
  2023-10-27 22:32 ` [Intel-xe] ✗ CI.checkpatch: warning " Patchwork
@ 2023-11-13 20:29   ` John Harrison
  0 siblings, 0 replies; 56+ messages in thread
From: John Harrison @ 2023-11-13 20:29 UTC (permalink / raw)
  To: intel-xe, Patchwork, Daniele Ceraolo Spurio

On 10/27/2023 15:32, Patchwork wrote:
> == Series Details ==
>
> Series: GSC FW loading
> URL   : https://patchwork.freedesktop.org/series/125717/
> State : warning
>
> == Summary ==
>
> + KERNEL=/kernel
> + git clone https://gitlab.freedesktop.org/drm/maintainer-tools mt
> Cloning into 'mt'...
> warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
> + git -C mt rev-list -n1 origin/master
> 63c2b6b160bca2df6efc7bc4cea6f442097d7854
> + cd /kernel
> + git config --global --add safe.directory /kernel
> + git log -n1
> commit bfb0ed12aee560b93dc3056de7832bcd95c6cb81
> Author: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Date:   Fri Oct 27 15:29:26 2023 -0700
>
>      drm/xe/gsc: Define GSC FW for MTL
>      
>      We track GSC FW based on its compatibility version, which is what
>      determines the interface it supports.
>      Also add a modparam override like the ones for GuC and HuC.
>      
>      Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>      Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
> + /mt/dim checkpatch f24c46200dc8fad700f51106e678d68d38496860 drm-intel
> 01e883a3a drm/xe: implement driver initiated function-reset
> f88539d04 fixup! drm/xe/guc: Report submission version of GuC firmware
> 590a5b6a1 drm/xe/uc: Rework uC version tracking
> -:206: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'p_' - possible side-effects?
> #206: FILE: drivers/gpu/drm/xe/xe_uc_fw.c:528:
> +#define print_uc_fw_version(p_, version_, prefix_, ...) \
> +do { \
> +	struct xe_uc_fw_version *ver_ = (version_); \
> +	if (ver_->build) \
> +		drm_printf(p_, prefix_ " version %u.%u.%u.%u\n", ##__VA_ARGS__, \
> +			   ver_->major, ver_->minor, \
> +			   ver_->patch, ver_->build); \
> +	else \
> +		drm_printf(p_, prefix_ " version %u.%u.%u\n", ##__VA_ARGS__, \
> +			  ver_->major, ver_->minor, ver_->patch); \
> +} while(0);
>
> -:206: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'prefix_' - possible side-effects?
> #206: FILE: drivers/gpu/drm/xe/xe_uc_fw.c:528:
> +#define print_uc_fw_version(p_, version_, prefix_, ...) \
> +do { \
> +	struct xe_uc_fw_version *ver_ = (version_); \
> +	if (ver_->build) \
> +		drm_printf(p_, prefix_ " version %u.%u.%u.%u\n", ##__VA_ARGS__, \
> +			   ver_->major, ver_->minor, \
> +			   ver_->patch, ver_->build); \
> +	else \
> +		drm_printf(p_, prefix_ " version %u.%u.%u\n", ##__VA_ARGS__, \
> +			  ver_->major, ver_->minor, ver_->patch); \
> +} while(0);
>
> -:206: WARNING:DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON: do {} while (0) macros should not be semicolon terminated
> #206: FILE: drivers/gpu/drm/xe/xe_uc_fw.c:528:
> +#define print_uc_fw_version(p_, version_, prefix_, ...) \
> +do { \
> +	struct xe_uc_fw_version *ver_ = (version_); \
> +	if (ver_->build) \
> +		drm_printf(p_, prefix_ " version %u.%u.%u.%u\n", ##__VA_ARGS__, \
> +			   ver_->major, ver_->minor, \
> +			   ver_->patch, ver_->build); \
> +	else \
> +		drm_printf(p_, prefix_ " version %u.%u.%u\n", ##__VA_ARGS__, \
> +			  ver_->major, ver_->minor, ver_->patch); \
> +} while(0);
This one needs to be fixed.

Likewise the white space issues below and another redundant ; and a 
redundant return.

John.


>
> -:216: ERROR:SPACING: space required before the open parenthesis '('
> #216: FILE: drivers/gpu/drm/xe/xe_uc_fw.c:538:
> +} while(0);
>
> total: 1 errors, 1 warnings, 2 checks, 298 lines checked
> 790a1435c drm/xe/gsc: Introduce GSC FW
> Traceback (most recent call last):
>    File "scripts/spdxcheck.py", line 6, in <module>
>      from ply import lex, yacc
> ModuleNotFoundError: No module named 'ply'
> Traceback (most recent call last):
>    File "scripts/spdxcheck.py", line 6, in <module>
>      from ply import lex, yacc
> ModuleNotFoundError: No module named 'ply'
> Traceback (most recent call last):
>    File "scripts/spdxcheck.py", line 6, in <module>
>      from ply import lex, yacc
> ModuleNotFoundError: No module named 'ply'
> -:31: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
> #31:
> new file mode 100644
>
> -:63: CHECK:UNNECESSARY_PARENTHESES: Unnecessary parentheses around 'gt != tile->media_gt'
> #63: FILE: drivers/gpu/drm/xe/xe_gsc.c:28:
> +	if (tile->media_gt && (gt != tile->media_gt)) {
>
> -:231: CHECK:LINE_SPACING: Please use a blank line after function/struct/union/enum declarations
> #231: FILE: drivers/gpu/drm/xe/xe_uc_fw_types.h:61:
>   };
> +#define XE_UC_FW_NUM_TYPES 3
>
> total: 0 errors, 1 warnings, 2 checks, 186 lines checked
> 7f147cee3 drm/xe/gsc: Parse GSC FW header
> -:48: ERROR:POINTER_LOCATION: "foo * bar" should be "foo *bar"
> #48: FILE: drivers/gpu/drm/xe/xe_uc_fw.c:493:
> +		struct xe_gsc * gsc = container_of(uc_fw, struct xe_gsc, fw);
>
> total: 1 errors, 0 warnings, 0 checks, 235 lines checked
> 8220f5ca7 drm/xe/gsc: GSC FW load
> Traceback (most recent call last):
>    File "scripts/spdxcheck.py", line 6, in <module>
>      from ply import lex, yacc
> ModuleNotFoundError: No module named 'ply'
> Traceback (most recent call last):
>    File "scripts/spdxcheck.py", line 6, in <module>
>      from ply import lex, yacc
> ModuleNotFoundError: No module named 'ply'
> -:24: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
> #24:
> new file mode 100644
>
> -:360: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
> #360: FILE: drivers/gpu/drm/xe/xe_gsc.c:268:
> +
> +}
>
> total: 0 errors, 1 warnings, 1 checks, 408 lines checked
> 65fcf37ec drm/xe/gsc: Implement WA 14015076503
> -:96: WARNING:RETURN_VOID: void function return statements are not generally useful
> #96: FILE: drivers/gpu/drm/xe/xe_gt.c:535:
> +	return;
> +}
>
> total: 0 errors, 1 warnings, 0 checks, 100 lines checked
> b70e25c8d drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload
> 4b7e69532 drm/xe/gsc: Add an interface for GSC packet submissions
> Traceback (most recent call last):
>    File "scripts/spdxcheck.py", line 6, in <module>
>      from ply import lex, yacc
> ModuleNotFoundError: No module named 'ply'
> Traceback (most recent call last):
>    File "scripts/spdxcheck.py", line 6, in <module>
>      from ply import lex, yacc
> ModuleNotFoundError: No module named 'ply'
> Traceback (most recent call last):
>    File "scripts/spdxcheck.py", line 6, in <module>
>      from ply import lex, yacc
> ModuleNotFoundError: No module named 'ply'
> -:38: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
> #38:
> new file mode 100644
>
> total: 0 errors, 1 warnings, 0 checks, 261 lines checked
> b0022f477 drm/xe/gsc: Query GSC compatibility version
> Traceback (most recent call last):
>    File "scripts/spdxcheck.py", line 6, in <module>
>      from ply import lex, yacc
> ModuleNotFoundError: No module named 'ply'
> -:14: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
> #14:
> new file mode 100644
>
> -:89: WARNING:LONG_LINE: line length of 102 exceeds 100 columns
> #89: FILE: drivers/gpu/drm/xe/xe_gsc.c:104:
> +	query_msg_wr(xe, map, wr_offset, header.command, MKHI_GFX_SRV_GET_HOST_COMPATIBILITY_VERSION);
>
> -:97: WARNING:LONG_LINE: line length of 101 exceeds 100 columns
> #97: FILE: drivers/gpu/drm/xe/xe_gsc.c:112:
> +	struct xe_uc_fw_version *compatibility = &gsc->fw.versions.found[XE_UC_FW_VER_COMPATIBILITY];
>
> -:108: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
> #108: FILE: drivers/gpu/drm/xe/xe_gsc.c:123:
> +	bo = xe_bo_create_pin_map(xe, tile, NULL, GSC_VER_PKT_SZ * 2,
> +			  ttm_bo_type_kernel,
>
> -:110: WARNING:ONE_SEMICOLON: Statements terminations use 1 semicolon
> #110: FILE: drivers/gpu/drm/xe/xe_gsc.c:125:
> +			  XE_BO_CREATE_GGTT_BIT);;
>
> total: 0 errors, 4 warnings, 1 checks, 185 lines checked
> 55c932772 drm/xe/gsc: Define GSCCS for MTL
> bfb0ed12a drm/xe/gsc: Define GSC FW for MTL
>
>


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

* Re: [Intel-xe]  ✗ CI.KUnit: failure for GSC FW loading
  2023-10-27 22:33 ` [Intel-xe] ✗ CI.KUnit: failure " Patchwork
@ 2023-11-13 20:30   ` John Harrison
  2023-11-13 21:13     ` Daniele Ceraolo Spurio
  0 siblings, 1 reply; 56+ messages in thread
From: John Harrison @ 2023-11-13 20:30 UTC (permalink / raw)
  To: intel-xe, Patchwork, Daniele Ceraolo Spurio

On 10/27/2023 15:33, Patchwork wrote:
> == Series Details ==
>
> Series: GSC FW loading
> URL   : https://patchwork.freedesktop.org/series/125717/
> State : failure
>
> == Summary ==
>
> + trap cleanup EXIT
> + /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
> stty: 'standard input': Inappropriate ioctl for device
> [22:32:58] Configuring KUnit Kernel ...
> Generating .config ...
> Populating config with:
> $ make ARCH=um O=.kunit olddefconfig
> [22:33:02] Building KUnit Kernel ...
> Populating config with:
> $ make ARCH=um O=.kunit olddefconfig
> Building with:
> $ make ARCH=um O=.kunit --jobs=48
> [22:33:23] Starting KUnit Kernel (1/1)...
> [22:33:23] ============================================================
> [22:33:23] ========================== xe_bo  ==========================
> [22:33:23] [SKIPPED] xe_ccs_migrate_kunit
> [22:33:23] [SKIPPED] xe_bo_evict_kunit
> [22:33:23] ===================== [SKIPPED] xe_bo ======================
> [22:33:23] ======================= xe_dma_buf  ========================
> [22:33:23] [SKIPPED] xe_dma_buf_kunit
> [22:33:23] =================== [SKIPPED] xe_dma_buf ===================
> [22:33:23] ======================= xe_migrate  ========================
> [22:33:23] [SKIPPED] xe_migrate_sanity_kunit
> [22:33:23] =================== [SKIPPED] xe_migrate ===================
> [22:33:23] ========================= xe_pci  ==========================
> [22:33:23] [PASSED] xe_gmdid_graphics_ip
> [22:33:23] # xe_gmdid_media_ip: ASSERTION FAILED at drivers/gpu/drm/xe/tests/xe_pci_test.c:45
> [22:33:23] Expected mask == 0, but
> [22:33:23]     mask == 67108864 (0x4000000)
> [22:33:23] [FAILED] xe_gmdid_media_ip
> [22:33:23] # xe_pci: pass:1 fail:1 skip:0 total:2
> [22:33:23] # Totals: pass:1 fail:1 skip:0 total:2
> [22:33:23] ===================== [FAILED] xe_pci ======================
I assume this failure is not related? Not seeing it could be connected 
but GSC is media tile specific...

John.

> [22:33:23] ========================= xe_rtp  ==========================
> [22:33:23] ================== xe_rtp_process_tests  ===================
> [22:33:23] [PASSED] coalesce-same-reg
> [22:33:23] [PASSED] no-match-no-add
> [22:33:23] [PASSED] no-match-no-add-multiple-rules
> [22:33:23] [PASSED] two-regs-two-entries
> [22:33:23] [PASSED] clr-one-set-other
> [22:33:23] [PASSED] set-field
> [22:33:23] [PASSED] conflict-duplicate
> [22:33:23] [PASSED] conflict-not-disjoint
> [22:33:23] [PASSED] conflict-reg-type
> [22:33:23] ============== [PASSED] xe_rtp_process_tests ===============
> [22:33:23] ===================== [PASSED] xe_rtp ======================
> [22:33:23] ========================== xe_wa  ==========================
> [22:33:23] ======================== xe_wa_gt  =========================
> [22:33:23] [PASSED] TIGERLAKE (B0)
> [22:33:23] [PASSED] DG1 (A0)
> [22:33:23] [PASSED] DG1 (B0)
> [22:33:23] [PASSED] ALDERLAKE_S (A0)
> [22:33:23] [PASSED] ALDERLAKE_S (B0)
> [22:33:23] [PASSED] ALDERLAKE_S (C0)
> [22:33:23] [PASSED] ALDERLAKE_S (D0)
> [22:33:23] [PASSED] ALDERLAKE_P (A0)
> [22:33:23] [PASSED] ALDERLAKE_P (B0)
> [22:33:23] [PASSED] ALDERLAKE_P (C0)
> [22:33:23] [PASSED] ALDERLAKE_S_RPLS (D0)
> [22:33:23] [PASSED] ALDERLAKE_P_RPLU (E0)
> [22:33:23] [PASSED] DG2_G10 (A0)
> [22:33:23] [PASSED] DG2_G10 (A1)
> [22:33:23] [PASSED] DG2_G10 (B0)
> [22:33:23] [PASSED] DG2_G10 (C0)
> [22:33:23] [PASSED] DG2_G11 (A0)
> [22:33:23] [PASSED] DG2_G11 (B0)
> [22:33:23] [PASSED] DG2_G11 (B1)
> [22:33:23] [PASSED] DG2_G12 (A0)
> [22:33:23] [PASSED] DG2_G12 (A1)
> [22:33:23] [PASSED] PVC (B0)
> [22:33:23] [PASSED] PVC (B1)
> [22:33:23] [PASSED] PVC (C0)
> [22:33:23] ==================== [PASSED] xe_wa_gt =====================
> [22:33:23] ====================== [PASSED] xe_wa ======================
> [22:33:23] ============================================================
> [22:33:23] Testing complete. Ran 39 tests: passed: 34, failed: 1, skipped: 4
> [22:33:23] Elapsed time: 24.485s total, 4.192s configuring, 20.173s building, 0.098s running
>
> + cleanup
> ++ stat -c %u:%g /kernel
> + chown -R 1003:1003 /kernel
>
>


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

* Re: [Intel-xe]  ✗ CI.KUnit: failure for GSC FW loading
  2023-11-13 20:30   ` John Harrison
@ 2023-11-13 21:13     ` Daniele Ceraolo Spurio
  0 siblings, 0 replies; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-13 21:13 UTC (permalink / raw)
  To: John Harrison, intel-xe, Patchwork



On 11/13/2023 12:30 PM, John Harrison wrote:
> On 10/27/2023 15:33, Patchwork wrote:
>> == Series Details ==
>>
>> Series: GSC FW loading
>> URL   : https://patchwork.freedesktop.org/series/125717/
>> State : failure
>>
>> == Summary ==
>>
>> + trap cleanup EXIT
>> + /kernel/tools/testing/kunit/kunit.py run --kunitconfig 
>> /kernel/drivers/gpu/drm/xe/.kunitconfig
>> stty: 'standard input': Inappropriate ioctl for device
>> [22:32:58] Configuring KUnit Kernel ...
>> Generating .config ...
>> Populating config with:
>> $ make ARCH=um O=.kunit olddefconfig
>> [22:33:02] Building KUnit Kernel ...
>> Populating config with:
>> $ make ARCH=um O=.kunit olddefconfig
>> Building with:
>> $ make ARCH=um O=.kunit --jobs=48
>> [22:33:23] Starting KUnit Kernel (1/1)...
>> [22:33:23] ============================================================
>> [22:33:23] ========================== xe_bo ==========================
>> [22:33:23] [SKIPPED] xe_ccs_migrate_kunit
>> [22:33:23] [SKIPPED] xe_bo_evict_kunit
>> [22:33:23] ===================== [SKIPPED] xe_bo ======================
>> [22:33:23] ======================= xe_dma_buf ========================
>> [22:33:23] [SKIPPED] xe_dma_buf_kunit
>> [22:33:23] =================== [SKIPPED] xe_dma_buf ===================
>> [22:33:23] ======================= xe_migrate ========================
>> [22:33:23] [SKIPPED] xe_migrate_sanity_kunit
>> [22:33:23] =================== [SKIPPED] xe_migrate ===================
>> [22:33:23] ========================= xe_pci ==========================
>> [22:33:23] [PASSED] xe_gmdid_graphics_ip
>> [22:33:23] # xe_gmdid_media_ip: ASSERTION FAILED at 
>> drivers/gpu/drm/xe/tests/xe_pci_test.c:45
>> [22:33:23] Expected mask == 0, but
>> [22:33:23]     mask == 67108864 (0x4000000)
>> [22:33:23] [FAILED] xe_gmdid_media_ip
>> [22:33:23] # xe_pci: pass:1 fail:1 skip:0 total:2
>> [22:33:23] # Totals: pass:1 fail:1 skip:0 total:2
>> [22:33:23] ===================== [FAILED] xe_pci ======================
> I assume this failure is not related? Not seeing it could be connected 
> but GSC is media tile specific...

It is actually related. The kunit checks that no unexpected engines are 
defined in the engine mask for the GT, so it needs an update to mark the 
GSC engine as expected on the media GT. I'll include it in the next spin.

Daniele

>
> John.
>
>> [22:33:23] ========================= xe_rtp  ==========================
>> [22:33:23] ================== xe_rtp_process_tests ===================
>> [22:33:23] [PASSED] coalesce-same-reg
>> [22:33:23] [PASSED] no-match-no-add
>> [22:33:23] [PASSED] no-match-no-add-multiple-rules
>> [22:33:23] [PASSED] two-regs-two-entries
>> [22:33:23] [PASSED] clr-one-set-other
>> [22:33:23] [PASSED] set-field
>> [22:33:23] [PASSED] conflict-duplicate
>> [22:33:23] [PASSED] conflict-not-disjoint
>> [22:33:23] [PASSED] conflict-reg-type
>> [22:33:23] ============== [PASSED] xe_rtp_process_tests ===============
>> [22:33:23] ===================== [PASSED] xe_rtp ======================
>> [22:33:23] ========================== xe_wa ==========================
>> [22:33:23] ======================== xe_wa_gt =========================
>> [22:33:23] [PASSED] TIGERLAKE (B0)
>> [22:33:23] [PASSED] DG1 (A0)
>> [22:33:23] [PASSED] DG1 (B0)
>> [22:33:23] [PASSED] ALDERLAKE_S (A0)
>> [22:33:23] [PASSED] ALDERLAKE_S (B0)
>> [22:33:23] [PASSED] ALDERLAKE_S (C0)
>> [22:33:23] [PASSED] ALDERLAKE_S (D0)
>> [22:33:23] [PASSED] ALDERLAKE_P (A0)
>> [22:33:23] [PASSED] ALDERLAKE_P (B0)
>> [22:33:23] [PASSED] ALDERLAKE_P (C0)
>> [22:33:23] [PASSED] ALDERLAKE_S_RPLS (D0)
>> [22:33:23] [PASSED] ALDERLAKE_P_RPLU (E0)
>> [22:33:23] [PASSED] DG2_G10 (A0)
>> [22:33:23] [PASSED] DG2_G10 (A1)
>> [22:33:23] [PASSED] DG2_G10 (B0)
>> [22:33:23] [PASSED] DG2_G10 (C0)
>> [22:33:23] [PASSED] DG2_G11 (A0)
>> [22:33:23] [PASSED] DG2_G11 (B0)
>> [22:33:23] [PASSED] DG2_G11 (B1)
>> [22:33:23] [PASSED] DG2_G12 (A0)
>> [22:33:23] [PASSED] DG2_G12 (A1)
>> [22:33:23] [PASSED] PVC (B0)
>> [22:33:23] [PASSED] PVC (B1)
>> [22:33:23] [PASSED] PVC (C0)
>> [22:33:23] ==================== [PASSED] xe_wa_gt =====================
>> [22:33:23] ====================== [PASSED] xe_wa ======================
>> [22:33:23] ============================================================
>> [22:33:23] Testing complete. Ran 39 tests: passed: 34, failed: 1, 
>> skipped: 4
>> [22:33:23] Elapsed time: 24.485s total, 4.192s configuring, 20.173s 
>> building, 0.098s running
>>
>> + cleanup
>> ++ stat -c %u:%g /kernel
>> + chown -R 1003:1003 /kernel
>>
>>
>


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

* Re: [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions
  2023-11-13 19:59   ` John Harrison
@ 2023-11-13 21:19     ` Daniele Ceraolo Spurio
  2023-11-14 19:32       ` John Harrison
  0 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-13 21:19 UTC (permalink / raw)
  To: John Harrison, intel-xe



On 11/13/2023 11:59 AM, John Harrison wrote:
> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>> Communication with the GSC FW is done via input/output buffers, whose
>> addresses are provided via a GSCCS command. The buffers contain a
>> generic header and a client-specific packet (e.g. PXP, HDCP); the
>> clients don't care about the header format and/or the GSCCS command in
>> the batch, they only care about their client-specific header. This patch
>> therefore introduces helpers that allow the callers to automatically
>> fill in the input header, submit the GSCCS job and decode the output
>> header, to make it so that the caller only needs to worry about their
>> client-specific input and output messages.
>>
>> NOTE: this patch by itself only adds the interface so it does nothing,
>> I've kept it separate for review but the plan is to squash it with the
>> follow up patch before merge, so that the interface and the user are
>> introduced at the same time.
>>
>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>> Cc: Suraj Kandpal <suraj.kandpal@intel.com>
>> ---
>>   drivers/gpu/drm/xe/Makefile                   |   1 +
>>   .../gpu/drm/xe/abi/gsc_command_header_abi.h   |  46 +++++
>>   .../gpu/drm/xe/instructions/xe_gsc_commands.h |   2 +
>>   drivers/gpu/drm/xe/xe_gsc_submit.c            | 170 ++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_gsc_submit.h            |  30 ++++
>>   5 files changed, 249 insertions(+)
>>   create mode 100644 drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.c
>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.h
>>
>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
>> index 4a442dcf4d79..876c122ad63c 100644
>> --- a/drivers/gpu/drm/xe/Makefile
>> +++ b/drivers/gpu/drm/xe/Makefile
>> @@ -58,6 +58,7 @@ xe-y += xe_bb.o \
>>       xe_force_wake.o \
>>       xe_ggtt.o \
>>       xe_gsc.o \
>> +    xe_gsc_submit.o \
>>       xe_gt.o \
>>       xe_gt_clock.o \
>>       xe_gt_debugfs.o \
>> diff --git a/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h 
>> b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>> new file mode 100644
>> index 000000000000..a4c2646803b5
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>> @@ -0,0 +1,46 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2023 Intel Corporation
>> + */
>> +
>> +#ifndef _ABI_GSC_COMMAND_HEADER_ABI_H
>> +#define _ABI_GSC_COMMAND_HEADER_ABI_H
>> +
>> +#include <linux/types.h>
>> +
>> +struct intel_gsc_mtl_header {
> Is this all really MTL platform specific? Or is it GSC version specific?
>
> Given that the reset of the driver is moving to be IP version based 
> instead of platform name based, it seems like this should also be 
> based in some kind of version rather than platform name. Or are the 
> GSC versions all just relative to the platform anyway?

GSC versioning is relative to the platform. As far as I'm aware the 
expectation so far is that this header will stay the same for LNL, but 
that's not a guarantee. Some of the binary headers for example are 
slightly different in the LNL blob (but the differences don't impact any 
of the areas we actually look at, so we can re-use the MTL code there as 
well). If you want to avoid the platform name I can call it 
intel_gsc_cmd_header for now and we can think about per-platform naming 
if we ever get different versions. Would that work?

Daniele

>
> Apart from that, it all looks good to me.
>
> John.
>


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

* Re: [Intel-xe] [PATCH 11/12] drm/xe/gsc: Define GSCCS for MTL
  2023-11-13 20:23   ` John Harrison
@ 2023-11-13 21:32     ` Daniele Ceraolo Spurio
  2023-11-14 19:39       ` John Harrison
  0 siblings, 1 reply; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-13 21:32 UTC (permalink / raw)
  To: John Harrison, intel-xe



On 11/13/2023 12:23 PM, John Harrison wrote:
> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>> Add the GSCCS to the media_xelpmp engine list. Note that since the
>> GSCCS is only used with the GSC FW, we can consider it disabled if we
>> don't have the FW available.
>>
>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>> ---
>>   drivers/gpu/drm/xe/xe_hw_engine.c | 20 ++++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_pci.c       |  2 +-
>>   2 files changed, 21 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c 
>> b/drivers/gpu/drm/xe/xe_hw_engine.c
>> index b5b084590888..142783177e45 100644
>> --- a/drivers/gpu/drm/xe/xe_hw_engine.c
>> +++ b/drivers/gpu/drm/xe/xe_hw_engine.c
>> @@ -26,6 +26,7 @@
>>   #include "xe_rtp.h"
>>   #include "xe_sched_job.h"
>>   #include "xe_tuning.h"
>> +#include "xe_uc_fw.h"
>>   #include "xe_wa.h"
>>     #define MAX_MMIO_BASES 3
>> @@ -610,6 +611,24 @@ static void read_compute_fuses(struct xe_gt *gt)
>>           read_compute_fuses_from_dss(gt);
>>   }
>>   +static void check_gsc_availability(struct xe_gt *gt)
>> +{
>> +    struct xe_device *xe = gt_to_xe(gt);
>> +
>> +    if (!(gt->info.engine_mask & BIT(XE_HW_ENGINE_GSCCS0)))
>> +        return;
>> +
>> +    /*
>> +     * The GSCCS is only used to communicate with the GSC FW, so if 
>> we don't
>> +     * have the FW there is nothing we need the engine for and can 
>> therefore
>> +     * skip its initialization.
> Is that correct? Is this testing against a firmware image being 
> available on the system or against a firmware blob being defined for 
> the platform?

This is post fw fetch, so it checks whether we have a blob or not.

>
> If the firmware is not available but was defined then presumably that 
> means that any feature that is reliant upon GSC is going to be broken 
> - HDCP, PXP, etc. It seems like that should warrant more than a 
> drm_info level message.

The fetch code will already print at drm_notice level. This log is not 
about the fetch failure, it is about the GSC engine being disabled as a 
consequence of that (or of the FW not being defined in the first place). 
PXP and HDCP should have their own checks for GSC availability when we 
add support for them (they do in i915).

>
> On the other hand, if the check is about whether a firmware blob is 
> defined for this platform then surely this code path wouldn't even be 
> taken in the first place? This can only be reached if actually trying 
> to load a firmware file at all, can't it?

I'm not sure what you mean here, this code path is part of the engine 
init flow, so we'll always take it.

Note that the main goal of this check is to allows us to define the GSC 
engine before the GSC FW, which is useful because the GSC FW is usually 
publicly released quite late for a new platform, while engines are one 
of the first things we define.

Daniele

>
> John.
>
>> +     */
>> +    if (!xe_uc_fw_is_available(&gt->uc.gsc.fw)) {
>> +        gt->info.engine_mask &= ~BIT(XE_HW_ENGINE_GSCCS0);
>> +        drm_info(&xe->drm, "gsccs disabled due to lack of FW\n");
>> +    }
>> +}
>> +
>>   int xe_hw_engines_init_early(struct xe_gt *gt)
>>   {
>>       int i;
>> @@ -617,6 +636,7 @@ int xe_hw_engines_init_early(struct xe_gt *gt)
>>       read_media_fuses(gt);
>>       read_copy_fuses(gt);
>>       read_compute_fuses(gt);
>> +    check_gsc_availability(gt);
>>         BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT < 
>> XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN);
>>       BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT > 
>> XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX);
>> diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
>> index 2fae45b9d88e..c09b51735ee4 100644
>> --- a/drivers/gpu/drm/xe/xe_pci.c
>> +++ b/drivers/gpu/drm/xe/xe_pci.c
>> @@ -197,7 +197,7 @@ static const struct xe_media_desc media_xelpmp = {
>>       .name = "Xe_LPM+",
>>       .hw_engine_mask =
>>           BIT(XE_HW_ENGINE_VCS0) | BIT(XE_HW_ENGINE_VCS2) |
>> -        BIT(XE_HW_ENGINE_VECS0),    /* TODO: add GSC0 */
>> +        BIT(XE_HW_ENGINE_VECS0) | BIT(XE_HW_ENGINE_GSCCS0)
>>   };
>>     static const struct xe_media_desc media_xe2 = {
>


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

* Re: [Intel-xe] [PATCH 12/12] drm/xe/gsc: Define GSC FW for MTL
  2023-11-13 20:26   ` John Harrison
@ 2023-11-13 21:33     ` Daniele Ceraolo Spurio
  0 siblings, 0 replies; 56+ messages in thread
From: Daniele Ceraolo Spurio @ 2023-11-13 21:33 UTC (permalink / raw)
  To: John Harrison, intel-xe



On 11/13/2023 12:26 PM, John Harrison wrote:
> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>> We track GSC FW based on its compatibility version, which is what
>> determines the interface it supports.
>> Also add a modparam override like the ones for GuC and HuC.
>>
>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>> ---
>>   drivers/gpu/drm/xe/xe_module.c |  5 +++++
>>   drivers/gpu/drm/xe/xe_module.h |  1 +
>>   drivers/gpu/drm/xe/xe_uc_fw.c  | 20 ++++++++++++--------
>>   3 files changed, 18 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_module.c 
>> b/drivers/gpu/drm/xe/xe_module.c
>> index 7194595e7f31..8df7aea64ad5 100644
>> --- a/drivers/gpu/drm/xe/xe_module.c
>> +++ b/drivers/gpu/drm/xe/xe_module.c
>> @@ -41,6 +41,11 @@ module_param_named_unsafe(huc_firmware_path, 
>> xe_huc_firmware_path, charp, 0400);
>>   MODULE_PARM_DESC(huc_firmware_path,
>>            "HuC firmware path to use instead of the default one - 
>> empty string disables");
>>   +char *xe_gsc_firmware_path;
>> +module_param_named_unsafe(gsc_firmware_path, xe_gsc_firmware_path, 
>> charp, 0400);
>> +MODULE_PARM_DESC(huc_firmware_path,
> s/huc/gsc/;

D'oh! Thanks for spotting this.

Daniele

>
> John.
>
>> +         "GSC firmware path to use instead of the default one - 
>> empty string disables");
>> +
>>   char *xe_param_force_probe = CONFIG_DRM_XE_FORCE_PROBE;
>>   module_param_named_unsafe(force_probe, xe_param_force_probe, charp, 
>> 0400);
>>   MODULE_PARM_DESC(force_probe,
>> diff --git a/drivers/gpu/drm/xe/xe_module.h 
>> b/drivers/gpu/drm/xe/xe_module.h
>> index e1da1e9ca5cb..7f49f95630d5 100644
>> --- a/drivers/gpu/drm/xe/xe_module.h
>> +++ b/drivers/gpu/drm/xe/xe_module.h
>> @@ -12,4 +12,5 @@ extern u32 xe_force_vram_bar_size;
>>   extern int xe_guc_log_level;
>>   extern char *xe_guc_firmware_path;
>>   extern char *xe_huc_firmware_path;
>> +extern char *xe_gsc_firmware_path;
>>   extern char *xe_param_force_probe;
>> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c 
>> b/drivers/gpu/drm/xe/xe_uc_fw.c
>> index f57476f57de9..c9360d918b96 100644
>> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
>> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
>> @@ -121,6 +121,10 @@ struct fw_blobs_by_type {
>>       fw_def(ROCKETLAKE,    no_ver(i915,    huc, tgl))        \
>>       fw_def(TIGERLAKE,    no_ver(i915,    huc,        tgl))
>>   +/* for the GSC FW we match the compatibility version and not the 
>> release one */
>> +#define XE_GSC_FIRMWARE_DEFS(fw_def, major_ver)        \
>> +    fw_def(METEORLAKE,    major_ver(i915,    gsc,    mtl,    1, 0))
>> +
>>   #define MAKE_FW_PATH(dir__, uc__, shortname__, version__)            \
>>       __stringify(dir__) "/" __stringify(shortname__) "_" 
>> __stringify(uc__) version__ ".bin"
>>   @@ -155,6 +159,7 @@ XE_GUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
>>                fw_filename_mmp_ver, fw_filename_major_ver)
>>   XE_HUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
>>                fw_filename_mmp_ver, fw_filename_no_ver)
>> +XE_GSC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE, fw_filename_major_ver)
>>     static struct xe_gt *
>>   __uc_fw_to_gt(struct xe_uc_fw *uc_fw, enum xe_uc_fw_type type)
>> @@ -196,23 +201,19 @@ uc_fw_auto_select(struct xe_device *xe, struct 
>> xe_uc_fw *uc_fw)
>>                        uc_fw_entry_mmp_ver,
>>                        uc_fw_entry_no_ver)
>>       };
>> +    static const struct uc_fw_entry entries_gsc[] = {
>> +        XE_GSC_FIRMWARE_DEFS(XE_UC_FW_ENTRY, uc_fw_entry_major_ver)
>> +    };
>>       static const struct fw_blobs_by_type 
>> blobs_all[XE_UC_FW_NUM_TYPES] = {
>>           [XE_UC_FW_TYPE_GUC] = { entries_guc, 
>> ARRAY_SIZE(entries_guc) },
>>           [XE_UC_FW_TYPE_HUC] = { entries_huc, 
>> ARRAY_SIZE(entries_huc) },
>> +        [XE_UC_FW_TYPE_GSC] = { entries_gsc, ARRAY_SIZE(entries_gsc) },
>>       };
>>       static const struct uc_fw_entry *entries;
>>       enum xe_platform p = xe->info.platform;
>>       u32 count;
>>       int i;
>>   -    /*
>> -     * GSC FW support is still not fully in place, so we're not 
>> defining
>> -     * the FW blob yet because we don't want the driver to attempt 
>> to load
>> -     * it until we're ready for it.
>> -     */
>> -    if (uc_fw->type == XE_UC_FW_TYPE_GSC)
>> -        return;
>> -
>>       xe_assert(xe, uc_fw->type < ARRAY_SIZE(blobs_all));
>>       entries = blobs_all[uc_fw->type].entries;
>>       count = blobs_all[uc_fw->type].count;
>> @@ -248,6 +249,9 @@ uc_fw_override(struct xe_uc_fw *uc_fw)
>>       case XE_UC_FW_TYPE_HUC:
>>           path_override = xe_huc_firmware_path;
>>           break;
>> +    case XE_UC_FW_TYPE_GSC:
>> +        path_override = xe_gsc_firmware_path;
>> +        break;
>>       default:
>>           break;
>>       }
>


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

* Re: [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions
  2023-11-13 21:19     ` Daniele Ceraolo Spurio
@ 2023-11-14 19:32       ` John Harrison
  0 siblings, 0 replies; 56+ messages in thread
From: John Harrison @ 2023-11-14 19:32 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 11/13/2023 13:19, Daniele Ceraolo Spurio wrote:
> On 11/13/2023 11:59 AM, John Harrison wrote:
>> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>>> Communication with the GSC FW is done via input/output buffers, whose
>>> addresses are provided via a GSCCS command. The buffers contain a
>>> generic header and a client-specific packet (e.g. PXP, HDCP); the
>>> clients don't care about the header format and/or the GSCCS command in
>>> the batch, they only care about their client-specific header. This 
>>> patch
>>> therefore introduces helpers that allow the callers to automatically
>>> fill in the input header, submit the GSCCS job and decode the output
>>> header, to make it so that the caller only needs to worry about their
>>> client-specific input and output messages.
>>>
>>> NOTE: this patch by itself only adds the interface so it does nothing,
>>> I've kept it separate for review but the plan is to squash it with the
>>> follow up patch before merge, so that the interface and the user are
>>> introduced at the same time.
>>>
>>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>>> Cc: Suraj Kandpal <suraj.kandpal@intel.com>
>>> ---
>>>   drivers/gpu/drm/xe/Makefile                   |   1 +
>>>   .../gpu/drm/xe/abi/gsc_command_header_abi.h   |  46 +++++
>>>   .../gpu/drm/xe/instructions/xe_gsc_commands.h |   2 +
>>>   drivers/gpu/drm/xe/xe_gsc_submit.c            | 170 
>>> ++++++++++++++++++
>>>   drivers/gpu/drm/xe/xe_gsc_submit.h            |  30 ++++
>>>   5 files changed, 249 insertions(+)
>>>   create mode 100644 drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.c
>>>   create mode 100644 drivers/gpu/drm/xe/xe_gsc_submit.h
>>>
>>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
>>> index 4a442dcf4d79..876c122ad63c 100644
>>> --- a/drivers/gpu/drm/xe/Makefile
>>> +++ b/drivers/gpu/drm/xe/Makefile
>>> @@ -58,6 +58,7 @@ xe-y += xe_bb.o \
>>>       xe_force_wake.o \
>>>       xe_ggtt.o \
>>>       xe_gsc.o \
>>> +    xe_gsc_submit.o \
>>>       xe_gt.o \
>>>       xe_gt_clock.o \
>>>       xe_gt_debugfs.o \
>>> diff --git a/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h 
>>> b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>>> new file mode 100644
>>> index 000000000000..a4c2646803b5
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/xe/abi/gsc_command_header_abi.h
>>> @@ -0,0 +1,46 @@
>>> +/* SPDX-License-Identifier: MIT */
>>> +/*
>>> + * Copyright © 2023 Intel Corporation
>>> + */
>>> +
>>> +#ifndef _ABI_GSC_COMMAND_HEADER_ABI_H
>>> +#define _ABI_GSC_COMMAND_HEADER_ABI_H
>>> +
>>> +#include <linux/types.h>
>>> +
>>> +struct intel_gsc_mtl_header {
>> Is this all really MTL platform specific? Or is it GSC version specific?
>>
>> Given that the reset of the driver is moving to be IP version based 
>> instead of platform name based, it seems like this should also be 
>> based in some kind of version rather than platform name. Or are the 
>> GSC versions all just relative to the platform anyway?
>
> GSC versioning is relative to the platform. As far as I'm aware the 
> expectation so far is that this header will stay the same for LNL, but 
> that's not a guarantee. Some of the binary headers for example are 
> slightly different in the LNL blob (but the differences don't impact 
> any of the areas we actually look at, so we can re-use the MTL code 
> there as well). If you want to avoid the platform name I can call it 
> intel_gsc_cmd_header for now and we can think about per-platform 
> naming if we ever get different versions. Would that work?
If the GSC team are saying that this is a platform specific interface 
then naming it by platform is fine by me. And keeping the name for 
future platforms doesn't seem like an issue. That's how everything else 
works - named by the device/platform/gen that introduced the feature and 
still used for future devices/platforms/gens until the next version 
comes along with a new name.

Reviewed-by: John Harrison <John.C.Harrison@Intel.Com>


>
> Daniele
>
>>
>> Apart from that, it all looks good to me.
>>
>> John.
>>
>


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

* Re: [Intel-xe] [PATCH 11/12] drm/xe/gsc: Define GSCCS for MTL
  2023-11-13 21:32     ` Daniele Ceraolo Spurio
@ 2023-11-14 19:39       ` John Harrison
  0 siblings, 0 replies; 56+ messages in thread
From: John Harrison @ 2023-11-14 19:39 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio, intel-xe

On 11/13/2023 13:32, Daniele Ceraolo Spurio wrote:
> On 11/13/2023 12:23 PM, John Harrison wrote:
>> On 10/27/2023 15:29, Daniele Ceraolo Spurio wrote:
>>> Add the GSCCS to the media_xelpmp engine list. Note that since the
>>> GSCCS is only used with the GSC FW, we can consider it disabled if we
>>> don't have the FW available.
>>>
>>> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
>>> Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
>>> ---
>>>   drivers/gpu/drm/xe/xe_hw_engine.c | 20 ++++++++++++++++++++
>>>   drivers/gpu/drm/xe/xe_pci.c       |  2 +-
>>>   2 files changed, 21 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c 
>>> b/drivers/gpu/drm/xe/xe_hw_engine.c
>>> index b5b084590888..142783177e45 100644
>>> --- a/drivers/gpu/drm/xe/xe_hw_engine.c
>>> +++ b/drivers/gpu/drm/xe/xe_hw_engine.c
>>> @@ -26,6 +26,7 @@
>>>   #include "xe_rtp.h"
>>>   #include "xe_sched_job.h"
>>>   #include "xe_tuning.h"
>>> +#include "xe_uc_fw.h"
>>>   #include "xe_wa.h"
>>>     #define MAX_MMIO_BASES 3
>>> @@ -610,6 +611,24 @@ static void read_compute_fuses(struct xe_gt *gt)
>>>           read_compute_fuses_from_dss(gt);
>>>   }
>>>   +static void check_gsc_availability(struct xe_gt *gt)
>>> +{
>>> +    struct xe_device *xe = gt_to_xe(gt);
>>> +
>>> +    if (!(gt->info.engine_mask & BIT(XE_HW_ENGINE_GSCCS0)))
>>> +        return;
>>> +
>>> +    /*
>>> +     * The GSCCS is only used to communicate with the GSC FW, so if 
>>> we don't
>>> +     * have the FW there is nothing we need the engine for and can 
>>> therefore
>>> +     * skip its initialization.
>> Is that correct? Is this testing against a firmware image being 
>> available on the system or against a firmware blob being defined for 
>> the platform?
>
> This is post fw fetch, so it checks whether we have a blob or not.
>
>>
>> If the firmware is not available but was defined then presumably that 
>> means that any feature that is reliant upon GSC is going to be broken 
>> - HDCP, PXP, etc. It seems like that should warrant more than a 
>> drm_info level message.
>
> The fetch code will already print at drm_notice level. This log is not 
> about the fetch failure, it is about the GSC engine being disabled as 
> a consequence of that (or of the FW not being defined in the first 
> place). PXP and HDCP should have their own checks for GSC availability 
> when we add support for them (they do in i915).
Okay. That makes sense.

>
>>
>> On the other hand, if the check is about whether a firmware blob is 
>> defined for this platform then surely this code path wouldn't even be 
>> taken in the first place? This can only be reached if actually trying 
>> to load a firmware file at all, can't it?
>
> I'm not sure what you mean here, this code path is part of the engine 
> init flow, so we'll always take it.
>
> Note that the main goal of this check is to allows us to define the 
> GSC engine before the GSC FW, which is useful because the GSC FW is 
> usually publicly released quite late for a new platform, while engines 
> are one of the first things we define.
Hmm. Meaning this is essentially pre-release only code? We generally try 
not to include internal only hacks in the public tree. Having said that, 
presumably this is not actually pre-release only. Exactly the same 
situation exists if the end user just does not have the firmware 
installed for any reason. In which case it seems reasonable given the 
above more specific checks in the firmware loading and PXP/HDCP code.

Reviewed-by: John Harrison <John.C.Harrison@Intel.com>


>
> Daniele
>
>>
>> John.
>>
>>> +     */
>>> +    if (!xe_uc_fw_is_available(&gt->uc.gsc.fw)) {
>>> +        gt->info.engine_mask &= ~BIT(XE_HW_ENGINE_GSCCS0);
>>> +        drm_info(&xe->drm, "gsccs disabled due to lack of FW\n");
>>> +    }
>>> +}
>>> +
>>>   int xe_hw_engines_init_early(struct xe_gt *gt)
>>>   {
>>>       int i;
>>> @@ -617,6 +636,7 @@ int xe_hw_engines_init_early(struct xe_gt *gt)
>>>       read_media_fuses(gt);
>>>       read_copy_fuses(gt);
>>>       read_compute_fuses(gt);
>>> +    check_gsc_availability(gt);
>>>         BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT < 
>>> XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN);
>>>       BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT > 
>>> XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX);
>>> diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
>>> index 2fae45b9d88e..c09b51735ee4 100644
>>> --- a/drivers/gpu/drm/xe/xe_pci.c
>>> +++ b/drivers/gpu/drm/xe/xe_pci.c
>>> @@ -197,7 +197,7 @@ static const struct xe_media_desc media_xelpmp = {
>>>       .name = "Xe_LPM+",
>>>       .hw_engine_mask =
>>>           BIT(XE_HW_ENGINE_VCS0) | BIT(XE_HW_ENGINE_VCS2) |
>>> -        BIT(XE_HW_ENGINE_VECS0),    /* TODO: add GSC0 */
>>> +        BIT(XE_HW_ENGINE_VECS0) | BIT(XE_HW_ENGINE_GSCCS0)
>>>   };
>>>     static const struct xe_media_desc media_xe2 = {
>>
>


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

end of thread, other threads:[~2023-11-14 19:39 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-27 22:29 [Intel-xe] [PATCH 00/12] GSC FW loading Daniele Ceraolo Spurio
2023-10-27 22:29 ` [Intel-xe] [PATCH 01/12] drm/xe: implement driver initiated function-reset Daniele Ceraolo Spurio
2023-11-07 23:46   ` John Harrison
2023-11-08 18:14     ` Daniele Ceraolo Spurio
2023-10-27 22:29 ` [Intel-xe] [PATCH 02/12] fixup! drm/xe/guc: Report submission version of GuC firmware Daniele Ceraolo Spurio
2023-10-31 14:09   ` Andrzej Hajda
2023-10-31 19:00     ` Daniele Ceraolo Spurio
2023-11-07 23:07   ` John Harrison
2023-11-07 23:24     ` Daniele Ceraolo Spurio
2023-11-07 23:38       ` John Harrison
2023-11-09 19:59         ` Daniele Ceraolo Spurio
2023-10-27 22:29 ` [Intel-xe] [PATCH 03/12] drm/xe/uc: Rework uC version tracking Daniele Ceraolo Spurio
2023-11-07 23:20   ` John Harrison
2023-10-27 22:29 ` [Intel-xe] [PATCH 04/12] drm/xe/gsc: Introduce GSC FW Daniele Ceraolo Spurio
2023-11-07 23:26   ` John Harrison
2023-11-07 23:32     ` Daniele Ceraolo Spurio
2023-11-07 23:52       ` John Harrison
2023-11-07 23:59         ` Daniele Ceraolo Spurio
2023-10-27 22:29 ` [Intel-xe] [PATCH 05/12] drm/xe/gsc: Parse GSC FW header Daniele Ceraolo Spurio
2023-11-07 23:45   ` John Harrison
2023-11-07 23:57     ` Daniele Ceraolo Spurio
2023-11-08  0:42       ` John Harrison
2023-10-27 22:29 ` [Intel-xe] [PATCH 06/12] drm/xe/gsc: GSC FW load Daniele Ceraolo Spurio
2023-11-08 22:17   ` John Harrison
2023-11-08 22:23     ` Daniele Ceraolo Spurio
2023-11-08 22:29       ` John Harrison
2023-10-27 22:29 ` [Intel-xe] [PATCH 07/12] drm/xe/gsc: Implement WA 14015076503 Daniele Ceraolo Spurio
2023-11-08 22:22   ` John Harrison
2023-11-08 22:35     ` Daniele Ceraolo Spurio
2023-11-08 22:40       ` John Harrison
2023-10-27 22:29 ` [Intel-xe] [PATCH 08/12] drm/xe/gsc: Trigger a driver flr to cleanup the GSC on unload Daniele Ceraolo Spurio
2023-11-08 22:24   ` John Harrison
2023-10-27 22:29 ` [Intel-xe] [PATCH 09/12] drm/xe/gsc: Add an interface for GSC packet submissions Daniele Ceraolo Spurio
2023-10-31  8:08   ` Kandpal, Suraj
2023-10-31 19:29     ` Daniele Ceraolo Spurio
2023-11-08  8:25       ` Kandpal, Suraj
2023-11-13 19:59   ` John Harrison
2023-11-13 21:19     ` Daniele Ceraolo Spurio
2023-11-14 19:32       ` John Harrison
2023-10-27 22:29 ` [Intel-xe] [PATCH 10/12] drm/xe/gsc: Query GSC compatibility version Daniele Ceraolo Spurio
2023-11-13 20:10   ` John Harrison
2023-10-27 22:29 ` [Intel-xe] [PATCH 11/12] drm/xe/gsc: Define GSCCS for MTL Daniele Ceraolo Spurio
2023-11-13 20:23   ` John Harrison
2023-11-13 21:32     ` Daniele Ceraolo Spurio
2023-11-14 19:39       ` John Harrison
2023-10-27 22:29 ` [Intel-xe] [PATCH 12/12] drm/xe/gsc: Define GSC FW " Daniele Ceraolo Spurio
2023-11-13 20:26   ` John Harrison
2023-11-13 21:33     ` Daniele Ceraolo Spurio
2023-10-27 22:32 ` [Intel-xe] ✓ CI.Patch_applied: success for GSC FW loading Patchwork
2023-10-27 22:32 ` [Intel-xe] ✗ CI.checkpatch: warning " Patchwork
2023-11-13 20:29   ` John Harrison
2023-10-27 22:33 ` [Intel-xe] ✗ CI.KUnit: failure " Patchwork
2023-11-13 20:30   ` John Harrison
2023-11-13 21:13     ` Daniele Ceraolo Spurio
2023-11-13 16:05 ` [Intel-xe] [PATCH 00/12] " Lucas De Marchi
2023-11-13 16:09   ` Daniele Ceraolo Spurio

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.