public inbox for intel-xe@lists.freedesktop.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/4] Add ocode late binding support for CRI
@ 2026-03-05 10:44 Badal Nilawar
  2026-03-05 10:44 ` [RFC PATCH 1/4] drm/xe/xe_late_bind_fw: Refactor pm flow Badal Nilawar
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Badal Nilawar @ 2026-03-05 10:44 UTC (permalink / raw)
  To: intel-xe
  Cc: anshuman.gupta, rodrigo.vivi, alexander.usyskin, michael.j.ruhl,
	daniele.ceraolospurio

Ocode is the OOBMSM telemetry/manageability firmware, and on CRI it is
loaded through late binding flow.

Dependancy: There is dependancy on mei side of patches to support ocode late binding,
	    which are not upstreamed yet. Hence, this patch is marked as RFC.

Badal Nilawar (4):
  drm/xe/xe_late_bind_fw: Refactor pm flow
  drm/xe/xe_late_bind_fw: Add support to load Ocode firmware on CRI
  drm/xe/xe_late_bind_fw: Track firmware load status
  drm/xe/xe_late_bind_fw: Enable late binding support for CRI

 drivers/gpu/drm/xe/xe_late_bind_fw.c       | 143 ++++++++++++++++++---
 drivers/gpu/drm/xe/xe_late_bind_fw.h       |   7 +-
 drivers/gpu/drm/xe/xe_late_bind_fw_types.h |  25 ++++
 drivers/gpu/drm/xe/xe_pci.c                |   1 +
 drivers/gpu/drm/xe/xe_pm.c                 |   9 +-
 5 files changed, 161 insertions(+), 24 deletions(-)

-- 
2.52.0


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

* [RFC PATCH 1/4] drm/xe/xe_late_bind_fw: Refactor pm flow
  2026-03-05 10:44 [RFC PATCH 0/4] Add ocode late binding support for CRI Badal Nilawar
@ 2026-03-05 10:44 ` Badal Nilawar
  2026-03-05 14:20   ` Rodrigo Vivi
  2026-03-05 10:44 ` [RFC PATCH 2/4] drm/xe/xe_late_bind_fw: Add support to load Ocode firmware on CRI Badal Nilawar
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Badal Nilawar @ 2026-03-05 10:44 UTC (permalink / raw)
  To: intel-xe
  Cc: anshuman.gupta, rodrigo.vivi, alexander.usyskin, michael.j.ruhl,
	daniele.ceraolospurio

Refactor late binding flow across suspend/resume by adding dedicated
pm functions.

Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
---
 drivers/gpu/drm/xe/xe_late_bind_fw.c | 32 +++++++++++++++++++++-------
 drivers/gpu/drm/xe/xe_late_bind_fw.h |  4 ++--
 drivers/gpu/drm/xe/xe_pm.c           |  6 +++---
 3 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw.c b/drivers/gpu/drm/xe/xe_late_bind_fw.c
index 768442ca7da6d..5ca25186dc0cc 100644
--- a/drivers/gpu/drm/xe/xe_late_bind_fw.c
+++ b/drivers/gpu/drm/xe/xe_late_bind_fw.c
@@ -193,7 +193,7 @@ static int xe_late_bind_fw_num_fans(struct xe_late_bind *late_bind, u32 *num_fan
 			     PCODE_MBOX(FAN_SPEED_CONTROL, FSC_READ_NUM_FANS, 0), num_fans, NULL);
 }
 
-void xe_late_bind_wait_for_worker_completion(struct xe_late_bind *late_bind)
+static void xe_late_bind_wait_for_worker_completion(struct xe_late_bind *late_bind)
 {
 	struct xe_device *xe = late_bind_to_xe(late_bind);
 	struct xe_late_bind_fw *lbfw;
@@ -269,18 +269,12 @@ static void xe_late_bind_work(struct work_struct *work)
 	xe_pm_runtime_put(xe);
 }
 
-int xe_late_bind_fw_load(struct xe_late_bind *late_bind)
+static int xe_late_bind_fw_load(struct xe_late_bind *late_bind)
 {
 	struct xe_device *xe = late_bind_to_xe(late_bind);
 	struct xe_late_bind_fw *lbfw;
 	int fw_id;
 
-	if (!late_bind->component_added)
-		return -ENODEV;
-
-	if (late_bind->disable)
-		return 0;
-
 	for (fw_id = 0; fw_id < XE_LB_FW_MAX_ID; fw_id++) {
 		lbfw = &late_bind->late_bind_fw[fw_id];
 		if (lbfw->payload) {
@@ -424,6 +418,28 @@ static void xe_late_bind_remove(void *arg)
 	}
 }
 
+void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind)
+{
+	if (!late_bind->component_added)
+		return;
+
+	if (late_bind->disable)
+		return;
+
+	xe_late_bind_wait_for_worker_completion(late_bind);
+}
+
+void xe_late_bind_pm_resume(struct xe_late_bind *late_bind)
+{
+	if (!late_bind->component_added)
+		return;
+
+	if (late_bind->disable)
+		return;
+
+	xe_late_bind_fw_load(late_bind);
+}
+
 /**
  * xe_late_bind_init() - add xe mei late binding component
  * @late_bind: pointer to late bind structure.
diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw.h b/drivers/gpu/drm/xe/xe_late_bind_fw.h
index 07e4373905395..8896fea3068e5 100644
--- a/drivers/gpu/drm/xe/xe_late_bind_fw.h
+++ b/drivers/gpu/drm/xe/xe_late_bind_fw.h
@@ -11,7 +11,7 @@
 struct xe_late_bind;
 
 int xe_late_bind_init(struct xe_late_bind *late_bind);
-int xe_late_bind_fw_load(struct xe_late_bind *late_bind);
-void xe_late_bind_wait_for_worker_completion(struct xe_late_bind *late_bind);
+void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind);
+void xe_late_bind_pm_resume(struct xe_late_bind *late_bind);
 
 #endif
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index 01185f10a8835..f85b12c1a85d2 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -182,7 +182,7 @@ int xe_pm_suspend(struct xe_device *xe)
 	if (err)
 		goto err;
 
-	xe_late_bind_wait_for_worker_completion(&xe->late_bind);
+	xe_late_bind_pm_suspend(&xe->late_bind);
 
 	for_each_gt(gt, xe, id)
 		xe_gt_suspend_prepare(gt);
@@ -284,7 +284,7 @@ int xe_pm_resume(struct xe_device *xe)
 	if (IS_VF_CCS_READY(xe))
 		xe_sriov_vf_ccs_register_context(xe);
 
-	xe_late_bind_fw_load(&xe->late_bind);
+	xe_late_bind_pm_resume(&xe->late_bind);
 
 	drm_dbg(&xe->drm, "Device resumed\n");
 	xe_pm_block_end_signalling();
@@ -698,7 +698,7 @@ int xe_pm_runtime_resume(struct xe_device *xe)
 		xe_sriov_vf_ccs_register_context(xe);
 
 	if (xe->d3cold.allowed)
-		xe_late_bind_fw_load(&xe->late_bind);
+		xe_late_bind_pm_resume(&xe->late_bind);
 
 out:
 	xe_rpm_lockmap_release(xe);
-- 
2.52.0


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

* [RFC PATCH 2/4] drm/xe/xe_late_bind_fw: Add support to load Ocode firmware on CRI
  2026-03-05 10:44 [RFC PATCH 0/4] Add ocode late binding support for CRI Badal Nilawar
  2026-03-05 10:44 ` [RFC PATCH 1/4] drm/xe/xe_late_bind_fw: Refactor pm flow Badal Nilawar
@ 2026-03-05 10:44 ` Badal Nilawar
  2026-03-05 23:38   ` Daniele Ceraolo Spurio
  2026-03-05 10:44 ` [RFC PATCH 3/4] drm/xe/xe_late_bind_fw: Track firmware load status Badal Nilawar
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Badal Nilawar @ 2026-03-05 10:44 UTC (permalink / raw)
  To: intel-xe
  Cc: anshuman.gupta, rodrigo.vivi, alexander.usyskin, michael.j.ruhl,
	daniele.ceraolospurio

Ocode is the OOBMSM telemetry/manageability firmware, and on CRI it is
loaded through late binding flow.

Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
---
 drivers/gpu/drm/xe/xe_late_bind_fw.c       | 49 +++++++++++++++++-----
 drivers/gpu/drm/xe/xe_late_bind_fw_types.h |  2 +
 2 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw.c b/drivers/gpu/drm/xe/xe_late_bind_fw.c
index 5ca25186dc0cc..d3ef2926517bd 100644
--- a/drivers/gpu/drm/xe/xe_late_bind_fw.c
+++ b/drivers/gpu/drm/xe/xe_late_bind_fw.c
@@ -33,10 +33,12 @@
 
 static const u32 fw_id_to_type[] = {
 		[XE_LB_FW_FAN_CONTROL] = INTEL_LB_TYPE_FAN_CONTROL,
+		[XE_LB_FW_OCODE] = INTEL_LB_TYPE_OCODE,
 	};
 
 static const char * const fw_id_to_name[] = {
 		[XE_LB_FW_FAN_CONTROL] = "fan_control",
+		[XE_LB_FW_OCODE] = "ocode",
 	};
 
 static struct xe_device *
@@ -179,6 +181,34 @@ static const char *xe_late_bind_parse_status(uint32_t status)
 		return "Invalid Payload";
 	case INTEL_LB_STATUS_TIMEOUT:
 		return "Timeout";
+	case INTEL_LB_STATUS_INTERNAL_ERROR:
+		return "Internal Error";
+	case INTEL_LB_STATUS_INVALID_FPT_TABLE:
+		return "Invalid FPT Table";
+	case INTEL_LB_STATUS_SIGNED_PAYLOAD_VERIFICATION_ERROR:
+		return "Signed Payload Verification Error";
+	case INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_CPD:
+		return "Signed Payload Invalid CPD";
+	case INTEL_LB_STATUS_SIGNED_PAYLOAD_FW_VERSION_MISMATCH:
+		return "Signed Payload FW Version Mismatch";
+	case INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_MANIFEST:
+		return "Signed Payload Invalid Manifest";
+	case INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_HASH:
+		return "Signed Payload Invalid Hash";
+	case INTEL_LB_STATUS_SIGNED_PAYLOAD_BINDING_TYPE_MISMATCH:
+		return "Signed Payload Binding type Mismatch";
+	case INTEL_LB_STATUS_SIGNED_PAYLOAD_HANDLE_SVN_FAILED:
+		return "Signed Payload Handle SVN Failed";
+	case INTEL_LB_STATUS_DESTINATION_MBOX_FAILURE:
+		return "Destination MBOX Failure";
+	case INTEL_LB_STATUS_MISSING_LOADING_PATCH:
+		return "Missing Loading Patch";
+	case INTEL_LB_STATUS_INVALID_COMMAND:
+		return "Invalid Command";
+	case INTEL_LB_STATUS_INVALID_HECI_HEADER:
+		return "Invalid HECI Header";
+	case INTEL_LB_STATUS_IP_ERROR_START:
+		return "IP Error Start";
 	default:
 		return "Unknown error";
 	}
@@ -264,7 +294,6 @@ static void xe_late_bind_work(struct work_struct *work)
 	/* Do not re-attempt fw load */
 	drmm_kfree(&xe->drm, (void *)lbfw->payload);
 	lbfw->payload = NULL;
-
 out:
 	xe_pm_runtime_put(xe);
 }
@@ -314,9 +343,14 @@ static int __xe_late_bind_fw_init(struct xe_late_bind *late_bind, u32 fw_id)
 			return 0;
 	}
 
-	snprintf(lb_fw->blob_path, sizeof(lb_fw->blob_path), "xe/%s_8086_%04x_%04x_%04x.bin",
-		 fw_id_to_name[lb_fw->id], pdev->device,
-		 pdev->subsystem_vendor, pdev->subsystem_device);
+	if (lb_fw->type == INTEL_LB_TYPE_OCODE) {
+		snprintf(lb_fw->blob_path, sizeof(lb_fw->blob_path), "xe/%s_8086_%04x.bin",
+			 fw_id_to_name[lb_fw->id], pdev->device);
+	} else {
+		snprintf(lb_fw->blob_path, sizeof(lb_fw->blob_path), "xe/%s_8086_%04x_%04x_%04x.bin",
+			 fw_id_to_name[lb_fw->id], pdev->device,
+			 pdev->subsystem_vendor, pdev->subsystem_device);
+	}
 
 	drm_dbg(&xe->drm, "Request late binding firmware %s\n", lb_fw->blob_path);
 	ret = firmware_request_nowarn(&fw, lb_fw->blob_path, xe->drm.dev);
@@ -326,13 +360,6 @@ static int __xe_late_bind_fw_init(struct xe_late_bind *late_bind, u32 fw_id)
 		return 0;
 	}
 
-	if (fw->size > XE_LB_MAX_PAYLOAD_SIZE) {
-		drm_err(&xe->drm, "Firmware %s size %zu is larger than max pay load size %u\n",
-			lb_fw->blob_path, fw->size, XE_LB_MAX_PAYLOAD_SIZE);
-		release_firmware(fw);
-		return -ENODATA;
-	}
-
 	ret = parse_lb_layout(lb_fw, fw->data, fw->size, "LTES");
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
index 2a8a985c37e71..a128e3f638a6c 100644
--- a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
+++ b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
@@ -20,6 +20,8 @@
 enum xe_late_bind_fw_id {
 	/** @XE_LB_FW_FAN_CONTROL: Fan control */
 	XE_LB_FW_FAN_CONTROL = 0,
+	/** @XE_LB_FW_OCODE: Ocode firmware */
+	XE_LB_FW_OCODE,
 	/** @XE_LB_FW_MAX_ID: Number of IDs */
 	XE_LB_FW_MAX_ID
 };
-- 
2.52.0


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

* [RFC PATCH 3/4] drm/xe/xe_late_bind_fw: Track firmware load status
  2026-03-05 10:44 [RFC PATCH 0/4] Add ocode late binding support for CRI Badal Nilawar
  2026-03-05 10:44 ` [RFC PATCH 1/4] drm/xe/xe_late_bind_fw: Refactor pm flow Badal Nilawar
  2026-03-05 10:44 ` [RFC PATCH 2/4] drm/xe/xe_late_bind_fw: Add support to load Ocode firmware on CRI Badal Nilawar
@ 2026-03-05 10:44 ` Badal Nilawar
  2026-03-05 23:52   ` Daniele Ceraolo Spurio
  2026-03-05 10:44 ` [RFC PATCH 4/4] drm/xe/xe_late_bind_fw: Enable late binding support for CRI Badal Nilawar
  2026-03-06 11:26 ` ✗ CI.KUnit: failure for Add ocode " Patchwork
  4 siblings, 1 reply; 9+ messages in thread
From: Badal Nilawar @ 2026-03-05 10:44 UTC (permalink / raw)
  To: intel-xe
  Cc: anshuman.gupta, rodrigo.vivi, alexander.usyskin, michael.j.ruhl,
	daniele.ceraolospurio

In CRI, Intel PMT depends on the ocode runtime status. Track the
late-binding firmware load status and expose an API, for xe_vsec driver,
to query it.

Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
---
 drivers/gpu/drm/xe/xe_late_bind_fw.c       | 68 +++++++++++++++++++++-
 drivers/gpu/drm/xe/xe_late_bind_fw.h       |  5 +-
 drivers/gpu/drm/xe/xe_late_bind_fw_types.h | 23 ++++++++
 drivers/gpu/drm/xe/xe_pm.c                 |  5 +-
 4 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw.c b/drivers/gpu/drm/xe/xe_late_bind_fw.c
index d3ef2926517bd..87137d6e4aaec 100644
--- a/drivers/gpu/drm/xe/xe_late_bind_fw.c
+++ b/drivers/gpu/drm/xe/xe_late_bind_fw.c
@@ -53,6 +53,32 @@ late_bind_fw_to_xe(struct xe_late_bind_fw *lb_fw)
 	return container_of(lb_fw, struct xe_device, late_bind.late_bind_fw[lb_fw->id]);
 }
 
+static const char *xe_late_bind_fw_status_to_str(enum xe_late_bind_fw_status status)
+{
+	switch (status) {
+	case XE_LB_FW_NOT_SUPPORTED:
+		return "Not Supported";
+	case XE_LB_FW_AVAILABLE:
+		return "Available";
+	case XE_LB_FW_RUNNING:
+		return "Running";
+	case XE_LB_FW_FAILED:
+		return "Failed";
+	default:
+		return "Unknown";
+	}
+}
+
+static void xe_late_bind_change_fw_status(struct xe_late_bind_fw *lb_fw,
+					  enum xe_late_bind_fw_status status)
+{
+	struct xe_device *xe = late_bind_fw_to_xe(lb_fw);
+
+	lb_fw->__status = status;
+	drm_dbg(&xe->drm, "%s firmware status changed to %s\n",
+		fw_id_to_name[lb_fw->id], xe_late_bind_fw_status_to_str(status));
+}
+
 /* Refer to the "Late Bind based Firmware Layout" documentation entry for details */
 static int parse_cpd_header(struct xe_late_bind_fw *lb_fw,
 			    const void *data, size_t size, const char *manifest_entry)
@@ -235,6 +261,13 @@ static void xe_late_bind_wait_for_worker_completion(struct xe_late_bind *late_bi
 			drm_dbg(&xe->drm, "Flush work: load %s firmware\n",
 				fw_id_to_name[lbfw->id]);
 			flush_work(&lbfw->work);
+
+			/*
+			 * flush is being called during component unbind, suspend etc.
+			 * So mark status XE_LB_FW_RUNNING -> XE_LB_FW_AVAILABLE
+			 */
+			if (lbfw->__status == XE_LB_FW_RUNNING)
+				xe_late_bind_change_fw_status(lbfw, XE_LB_FW_AVAILABLE);
 		}
 	}
 }
@@ -282,6 +315,7 @@ static void xe_late_bind_work(struct work_struct *work)
 	if (!ret) {
 		drm_dbg(&xe->drm, "Load %s firmware successful\n",
 			fw_id_to_name[lbfw->id]);
+		xe_late_bind_change_fw_status(lbfw, XE_LB_FW_RUNNING);
 		goto out;
 	}
 
@@ -294,10 +328,23 @@ static void xe_late_bind_work(struct work_struct *work)
 	/* Do not re-attempt fw load */
 	drmm_kfree(&xe->drm, (void *)lbfw->payload);
 	lbfw->payload = NULL;
+	xe_late_bind_change_fw_status(lbfw, XE_LB_FW_FAILED);
 out:
 	xe_pm_runtime_put(xe);
 }
 
+static void  xe_late_bind_fw_stop(struct xe_late_bind *late_bind)
+{
+	struct xe_late_bind_fw *lbfw;
+	int fw_id;
+
+	for (fw_id = 0; fw_id < XE_LB_FW_MAX_ID; fw_id++) {
+		lbfw = &late_bind->late_bind_fw[fw_id];
+		if (lbfw->payload && lbfw->status == XE_LB_FW_RUNNING)
+			xe_late_bind_change_fw_status(lbfw, XE_LB_FW_AVAILABLE);
+	}
+}
+
 static int xe_late_bind_fw_load(struct xe_late_bind *late_bind)
 {
 	struct xe_device *xe = late_bind_to_xe(late_bind);
@@ -331,6 +378,7 @@ static int __xe_late_bind_fw_init(struct xe_late_bind *late_bind, u32 fw_id)
 	lb_fw->id = fw_id;
 	lb_fw->type = fw_id_to_type[lb_fw->id];
 	lb_fw->flags &= ~INTEL_LB_FLAG_IS_PERSISTENT;
+	xe_late_bind_change_fw_status(lb_fw, XE_LB_FW_NOT_SUPPORTED);
 
 	if (lb_fw->type == INTEL_LB_TYPE_FAN_CONTROL) {
 		ret = xe_late_bind_fw_num_fans(late_bind, &num_fans);
@@ -379,6 +427,7 @@ static int __xe_late_bind_fw_init(struct xe_late_bind *late_bind, u32 fw_id)
 	memcpy((void *)lb_fw->payload, fw->data, lb_fw->payload_size);
 	release_firmware(fw);
 	INIT_WORK(&lb_fw->work, xe_late_bind_work);
+	xe_late_bind_change_fw_status(lb_fw, XE_LB_FW_AVAILABLE);
 
 	return 0;
 }
@@ -445,15 +494,30 @@ static void xe_late_bind_remove(void *arg)
 	}
 }
 
-void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind)
+/**
+ * xe_late_bind_ocode_status() - get ocode late bind firmware status
+ * @xe: pointer to xe device.
+ *
+ * Return: 0 if unsupported, 1 if available, 2 if running, 3 if failed.
+ */
+int xe_late_bind_ocode_status(struct xe_device *xe)
+{
+	struct xe_late_bind_fw *lbfw = &xe->late_bind.late_bind_fw[XE_LB_FW_OCODE];
+
+	return lbfw->status;
+}
+
+void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind, bool is_runtime)
 {
 	if (!late_bind->component_added)
 		return;
 
 	if (late_bind->disable)
 		return;
+	if (!is_runtime)
+		xe_late_bind_wait_for_worker_completion(late_bind);
 
-	xe_late_bind_wait_for_worker_completion(late_bind);
+	xe_late_bind_fw_stop(late_bind);
 }
 
 void xe_late_bind_pm_resume(struct xe_late_bind *late_bind)
diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw.h b/drivers/gpu/drm/xe/xe_late_bind_fw.h
index 8896fea3068e5..b441f5789f24b 100644
--- a/drivers/gpu/drm/xe/xe_late_bind_fw.h
+++ b/drivers/gpu/drm/xe/xe_late_bind_fw.h
@@ -9,9 +9,10 @@
 #include <linux/types.h>
 
 struct xe_late_bind;
+struct xe_device;
 
 int xe_late_bind_init(struct xe_late_bind *late_bind);
-void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind);
+void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind, bool is_runtime);
 void xe_late_bind_pm_resume(struct xe_late_bind *late_bind);
-
+int xe_late_bind_ocode_status(struct xe_device *xe);
 #endif
diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
index a128e3f638a6c..4cdbd775b103e 100644
--- a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
+++ b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
@@ -26,6 +26,20 @@ enum xe_late_bind_fw_id {
 	XE_LB_FW_MAX_ID
 };
 
+/**
+ * enum xe_late_bind_fw_status - enum to determine late binding fw status
+ */
+enum xe_late_bind_fw_status {
+	/** @XE_LB_FW_NOT_SUPPORTED: firmware not available/supported */
+	XE_LB_FW_NOT_SUPPORTED,
+	/** @XE_LB_FW_AVAILABLE: firmware found and copied to memory */
+	XE_LB_FW_AVAILABLE,
+	/** @XE_LB_FW_RUNNING: firmware is running */
+	XE_LB_FW_RUNNING,
+	/** @XE_LB_FW_FAILED: firmware load is failed */
+	XE_LB_FW_FAILED,
+};
+
 /**
  * struct xe_late_bind_fw
  */
@@ -46,6 +60,15 @@ struct xe_late_bind_fw {
 	struct work_struct work;
 	/** @version: late binding blob manifest version */
 	struct gsc_version version;
+	union {
+		/** @status: firmware load status */
+		const enum xe_late_bind_fw_status status;
+		/**
+		 * @__status: private firmware load status - only to be used
+		 * by firmware loading code
+		 */
+		enum xe_late_bind_fw_status __status;
+	};
 };
 
 /**
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index f85b12c1a85d2..9aa873f57b5ad 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -182,7 +182,7 @@ int xe_pm_suspend(struct xe_device *xe)
 	if (err)
 		goto err;
 
-	xe_late_bind_pm_suspend(&xe->late_bind);
+	xe_late_bind_pm_suspend(&xe->late_bind, false);
 
 	for_each_gt(gt, xe, id)
 		xe_gt_suspend_prepare(gt);
@@ -612,6 +612,9 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
 			goto out_resume;
 	}
 
+	if (xe->d3cold.allowed)
+		xe_late_bind_pm_suspend(&xe->late_bind, true);
+
 	xe_irq_suspend(xe);
 
 	xe_display_pm_runtime_suspend_late(xe);
-- 
2.52.0


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

* [RFC PATCH 4/4] drm/xe/xe_late_bind_fw: Enable late binding support for CRI
  2026-03-05 10:44 [RFC PATCH 0/4] Add ocode late binding support for CRI Badal Nilawar
                   ` (2 preceding siblings ...)
  2026-03-05 10:44 ` [RFC PATCH 3/4] drm/xe/xe_late_bind_fw: Track firmware load status Badal Nilawar
@ 2026-03-05 10:44 ` Badal Nilawar
  2026-03-06 11:26 ` ✗ CI.KUnit: failure for Add ocode " Patchwork
  4 siblings, 0 replies; 9+ messages in thread
From: Badal Nilawar @ 2026-03-05 10:44 UTC (permalink / raw)
  To: intel-xe
  Cc: anshuman.gupta, rodrigo.vivi, alexander.usyskin, michael.j.ruhl,
	daniele.ceraolospurio

Enable late binding support for CRI

Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
---
 drivers/gpu/drm/xe/xe_pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index 29f976e66848c..7564eebd6a654 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -461,6 +461,7 @@ static const struct xe_device_desc cri_desc = {
 	.has_mbx_power_limits = true,
 	.has_mbx_thermal_info = true,
 	.has_mert = true,
+	.has_late_bind = true,
 	.has_pre_prod_wa = 1,
 	.has_soc_remapper_sysctrl = true,
 	.has_soc_remapper_telem = true,
-- 
2.52.0


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

* Re: [RFC PATCH 1/4] drm/xe/xe_late_bind_fw: Refactor pm flow
  2026-03-05 10:44 ` [RFC PATCH 1/4] drm/xe/xe_late_bind_fw: Refactor pm flow Badal Nilawar
@ 2026-03-05 14:20   ` Rodrigo Vivi
  0 siblings, 0 replies; 9+ messages in thread
From: Rodrigo Vivi @ 2026-03-05 14:20 UTC (permalink / raw)
  To: Badal Nilawar
  Cc: intel-xe, anshuman.gupta, alexander.usyskin, michael.j.ruhl,
	daniele.ceraolospurio

On Thu, Mar 05, 2026 at 04:14:42PM +0530, Badal Nilawar wrote:
> Refactor late binding flow across suspend/resume by adding dedicated
> pm functions.
> 
> Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_late_bind_fw.c | 32 +++++++++++++++++++++-------
>  drivers/gpu/drm/xe/xe_late_bind_fw.h |  4 ++--
>  drivers/gpu/drm/xe/xe_pm.c           |  6 +++---
>  3 files changed, 29 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw.c b/drivers/gpu/drm/xe/xe_late_bind_fw.c
> index 768442ca7da6d..5ca25186dc0cc 100644
> --- a/drivers/gpu/drm/xe/xe_late_bind_fw.c
> +++ b/drivers/gpu/drm/xe/xe_late_bind_fw.c
> @@ -193,7 +193,7 @@ static int xe_late_bind_fw_num_fans(struct xe_late_bind *late_bind, u32 *num_fan
>  			     PCODE_MBOX(FAN_SPEED_CONTROL, FSC_READ_NUM_FANS, 0), num_fans, NULL);
>  }
>  
> -void xe_late_bind_wait_for_worker_completion(struct xe_late_bind *late_bind)
> +static void xe_late_bind_wait_for_worker_completion(struct xe_late_bind *late_bind)

since it is now static, you can perhaps remove entirely the
prefix 'xe_late_bind_' to make it shorter.

I prefer without it but I don't believe it hurts to keep it. Up to you:

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

>  {
>  	struct xe_device *xe = late_bind_to_xe(late_bind);
>  	struct xe_late_bind_fw *lbfw;
> @@ -269,18 +269,12 @@ static void xe_late_bind_work(struct work_struct *work)
>  	xe_pm_runtime_put(xe);
>  }
>  
> -int xe_late_bind_fw_load(struct xe_late_bind *late_bind)
> +static int xe_late_bind_fw_load(struct xe_late_bind *late_bind)
>  {
>  	struct xe_device *xe = late_bind_to_xe(late_bind);
>  	struct xe_late_bind_fw *lbfw;
>  	int fw_id;
>  
> -	if (!late_bind->component_added)
> -		return -ENODEV;
> -
> -	if (late_bind->disable)
> -		return 0;
> -
>  	for (fw_id = 0; fw_id < XE_LB_FW_MAX_ID; fw_id++) {
>  		lbfw = &late_bind->late_bind_fw[fw_id];
>  		if (lbfw->payload) {
> @@ -424,6 +418,28 @@ static void xe_late_bind_remove(void *arg)
>  	}
>  }
>  
> +void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind)
> +{
> +	if (!late_bind->component_added)
> +		return;
> +
> +	if (late_bind->disable)
> +		return;
> +
> +	xe_late_bind_wait_for_worker_completion(late_bind);
> +}
> +
> +void xe_late_bind_pm_resume(struct xe_late_bind *late_bind)
> +{
> +	if (!late_bind->component_added)
> +		return;
> +
> +	if (late_bind->disable)
> +		return;
> +
> +	xe_late_bind_fw_load(late_bind);
> +}
> +
>  /**
>   * xe_late_bind_init() - add xe mei late binding component
>   * @late_bind: pointer to late bind structure.
> diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw.h b/drivers/gpu/drm/xe/xe_late_bind_fw.h
> index 07e4373905395..8896fea3068e5 100644
> --- a/drivers/gpu/drm/xe/xe_late_bind_fw.h
> +++ b/drivers/gpu/drm/xe/xe_late_bind_fw.h
> @@ -11,7 +11,7 @@
>  struct xe_late_bind;
>  
>  int xe_late_bind_init(struct xe_late_bind *late_bind);
> -int xe_late_bind_fw_load(struct xe_late_bind *late_bind);
> -void xe_late_bind_wait_for_worker_completion(struct xe_late_bind *late_bind);
> +void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind);
> +void xe_late_bind_pm_resume(struct xe_late_bind *late_bind);
>  
>  #endif
> diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
> index 01185f10a8835..f85b12c1a85d2 100644
> --- a/drivers/gpu/drm/xe/xe_pm.c
> +++ b/drivers/gpu/drm/xe/xe_pm.c
> @@ -182,7 +182,7 @@ int xe_pm_suspend(struct xe_device *xe)
>  	if (err)
>  		goto err;
>  
> -	xe_late_bind_wait_for_worker_completion(&xe->late_bind);
> +	xe_late_bind_pm_suspend(&xe->late_bind);
>  
>  	for_each_gt(gt, xe, id)
>  		xe_gt_suspend_prepare(gt);
> @@ -284,7 +284,7 @@ int xe_pm_resume(struct xe_device *xe)
>  	if (IS_VF_CCS_READY(xe))
>  		xe_sriov_vf_ccs_register_context(xe);
>  
> -	xe_late_bind_fw_load(&xe->late_bind);
> +	xe_late_bind_pm_resume(&xe->late_bind);
>  
>  	drm_dbg(&xe->drm, "Device resumed\n");
>  	xe_pm_block_end_signalling();
> @@ -698,7 +698,7 @@ int xe_pm_runtime_resume(struct xe_device *xe)
>  		xe_sriov_vf_ccs_register_context(xe);
>  
>  	if (xe->d3cold.allowed)
> -		xe_late_bind_fw_load(&xe->late_bind);
> +		xe_late_bind_pm_resume(&xe->late_bind);
>  
>  out:
>  	xe_rpm_lockmap_release(xe);
> -- 
> 2.52.0
> 

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

* Re: [RFC PATCH 2/4] drm/xe/xe_late_bind_fw: Add support to load Ocode firmware on CRI
  2026-03-05 10:44 ` [RFC PATCH 2/4] drm/xe/xe_late_bind_fw: Add support to load Ocode firmware on CRI Badal Nilawar
@ 2026-03-05 23:38   ` Daniele Ceraolo Spurio
  0 siblings, 0 replies; 9+ messages in thread
From: Daniele Ceraolo Spurio @ 2026-03-05 23:38 UTC (permalink / raw)
  To: Badal Nilawar, intel-xe
  Cc: anshuman.gupta, rodrigo.vivi, alexander.usyskin, michael.j.ruhl



On 3/5/2026 2:44 AM, Badal Nilawar wrote:
> Ocode is the OOBMSM telemetry/manageability firmware, and on CRI it is
> loaded through late binding flow.
>
> Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
> ---
>   drivers/gpu/drm/xe/xe_late_bind_fw.c       | 49 +++++++++++++++++-----
>   drivers/gpu/drm/xe/xe_late_bind_fw_types.h |  2 +
>   2 files changed, 40 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw.c b/drivers/gpu/drm/xe/xe_late_bind_fw.c
> index 5ca25186dc0cc..d3ef2926517bd 100644
> --- a/drivers/gpu/drm/xe/xe_late_bind_fw.c
> +++ b/drivers/gpu/drm/xe/xe_late_bind_fw.c
> @@ -33,10 +33,12 @@
>   
>   static const u32 fw_id_to_type[] = {
>   		[XE_LB_FW_FAN_CONTROL] = INTEL_LB_TYPE_FAN_CONTROL,
> +		[XE_LB_FW_OCODE] = INTEL_LB_TYPE_OCODE,
>   	};
>   
>   static const char * const fw_id_to_name[] = {
>   		[XE_LB_FW_FAN_CONTROL] = "fan_control",
> +		[XE_LB_FW_OCODE] = "ocode",
>   	};
>   
>   static struct xe_device *
> @@ -179,6 +181,34 @@ static const char *xe_late_bind_parse_status(uint32_t status)
>   		return "Invalid Payload";
>   	case INTEL_LB_STATUS_TIMEOUT:
>   		return "Timeout";
> +	case INTEL_LB_STATUS_INTERNAL_ERROR:
> +		return "Internal Error";
> +	case INTEL_LB_STATUS_INVALID_FPT_TABLE:
> +		return "Invalid FPT Table";
> +	case INTEL_LB_STATUS_SIGNED_PAYLOAD_VERIFICATION_ERROR:
> +		return "Signed Payload Verification Error";
> +	case INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_CPD:
> +		return "Signed Payload Invalid CPD";
> +	case INTEL_LB_STATUS_SIGNED_PAYLOAD_FW_VERSION_MISMATCH:
> +		return "Signed Payload FW Version Mismatch";
> +	case INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_MANIFEST:
> +		return "Signed Payload Invalid Manifest";
> +	case INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_HASH:
> +		return "Signed Payload Invalid Hash";
> +	case INTEL_LB_STATUS_SIGNED_PAYLOAD_BINDING_TYPE_MISMATCH:
> +		return "Signed Payload Binding type Mismatch";
> +	case INTEL_LB_STATUS_SIGNED_PAYLOAD_HANDLE_SVN_FAILED:
> +		return "Signed Payload Handle SVN Failed";
> +	case INTEL_LB_STATUS_DESTINATION_MBOX_FAILURE:
> +		return "Destination MBOX Failure";
> +	case INTEL_LB_STATUS_MISSING_LOADING_PATCH:
> +		return "Missing Loading Patch";
> +	case INTEL_LB_STATUS_INVALID_COMMAND:
> +		return "Invalid Command";
> +	case INTEL_LB_STATUS_INVALID_HECI_HEADER:
> +		return "Invalid HECI Header";
> +	case INTEL_LB_STATUS_IP_ERROR_START:
> +		return "IP Error Start";
>   	default:
>   		return "Unknown error";
>   	}
> @@ -264,7 +294,6 @@ static void xe_late_bind_work(struct work_struct *work)
>   	/* Do not re-attempt fw load */
>   	drmm_kfree(&xe->drm, (void *)lbfw->payload);
>   	lbfw->payload = NULL;
> -

I think it'd better to keep an empty line before the "out" label.

>   out:
>   	xe_pm_runtime_put(xe);
>   }
> @@ -314,9 +343,14 @@ static int __xe_late_bind_fw_init(struct xe_late_bind *late_bind, u32 fw_id)
>   			return 0;
>   	}
>   
> -	snprintf(lb_fw->blob_path, sizeof(lb_fw->blob_path), "xe/%s_8086_%04x_%04x_%04x.bin",
> -		 fw_id_to_name[lb_fw->id], pdev->device,
> -		 pdev->subsystem_vendor, pdev->subsystem_device);
> +	if (lb_fw->type == INTEL_LB_TYPE_OCODE) {
> +		snprintf(lb_fw->blob_path, sizeof(lb_fw->blob_path), "xe/%s_8086_%04x.bin",
> +			 fw_id_to_name[lb_fw->id], pdev->device);

Are we expecting different ocodes for each PCI id? if not, we could name 
this like the other fw binaries as <platform>_ocode.bin (e.g., 
cri_ocode.bin)

> +	} else {
> +		snprintf(lb_fw->blob_path, sizeof(lb_fw->blob_path), "xe/%s_8086_%04x_%04x_%04x.bin",
> +			 fw_id_to_name[lb_fw->id], pdev->device,
> +			 pdev->subsystem_vendor, pdev->subsystem_device);
> +	}
>   
>   	drm_dbg(&xe->drm, "Request late binding firmware %s\n", lb_fw->blob_path);
>   	ret = firmware_request_nowarn(&fw, lb_fw->blob_path, xe->drm.dev);
> @@ -326,13 +360,6 @@ static int __xe_late_bind_fw_init(struct xe_late_bind *late_bind, u32 fw_id)
>   		return 0;
>   	}
>   
> -	if (fw->size > XE_LB_MAX_PAYLOAD_SIZE) {
> -		drm_err(&xe->drm, "Firmware %s size %zu is larger than max pay load size %u\n",
> -			lb_fw->blob_path, fw->size, XE_LB_MAX_PAYLOAD_SIZE);
> -		release_firmware(fw);
> -		return -ENODATA;
> -	}

Why is this check being removed? is MEI/CSC now going to accept bigger 
payloads?

> -
>   	ret = parse_lb_layout(lb_fw, fw->data, fw->size, "LTES");
>   	if (ret)
>   		return ret;
> diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
> index 2a8a985c37e71..a128e3f638a6c 100644
> --- a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
> +++ b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
> @@ -20,6 +20,8 @@
>   enum xe_late_bind_fw_id {
>   	/** @XE_LB_FW_FAN_CONTROL: Fan control */
>   	XE_LB_FW_FAN_CONTROL = 0,
> +	/** @XE_LB_FW_OCODE: Ocode firmware */
> +	XE_LB_FW_OCODE,

This will now automatically look for ocode for bmg as well. not an 
issue, but potentially noise in dmesg. Maybe we could change 
has_late_bind to be a mask of supported fw types? that way we can set it 
to BIT(XE_LB_FW_FAN_CONTROL) on BMG and BIT(XE_LB_FW_OCODE) on CRI and 
skip the FW type if not set in the mask. Not a blocker.

Daniele

>   	/** @XE_LB_FW_MAX_ID: Number of IDs */
>   	XE_LB_FW_MAX_ID
>   };


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

* Re: [RFC PATCH 3/4] drm/xe/xe_late_bind_fw: Track firmware load status
  2026-03-05 10:44 ` [RFC PATCH 3/4] drm/xe/xe_late_bind_fw: Track firmware load status Badal Nilawar
@ 2026-03-05 23:52   ` Daniele Ceraolo Spurio
  0 siblings, 0 replies; 9+ messages in thread
From: Daniele Ceraolo Spurio @ 2026-03-05 23:52 UTC (permalink / raw)
  To: Badal Nilawar, intel-xe
  Cc: anshuman.gupta, rodrigo.vivi, alexander.usyskin, michael.j.ruhl



On 3/5/2026 2:44 AM, Badal Nilawar wrote:
> In CRI, Intel PMT depends on the ocode runtime status. Track the
> late-binding firmware load status and expose an API, for xe_vsec driver,
> to query it.

I think it would be better to send this patch with the series that adds 
the xe_vsec changes, otherwise we have no idea from a review POV on how 
you plan to use the new exposed API.

> Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
> ---
>   drivers/gpu/drm/xe/xe_late_bind_fw.c       | 68 +++++++++++++++++++++-
>   drivers/gpu/drm/xe/xe_late_bind_fw.h       |  5 +-
>   drivers/gpu/drm/xe/xe_late_bind_fw_types.h | 23 ++++++++
>   drivers/gpu/drm/xe/xe_pm.c                 |  5 +-
>   4 files changed, 96 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw.c b/drivers/gpu/drm/xe/xe_late_bind_fw.c
> index d3ef2926517bd..87137d6e4aaec 100644
> --- a/drivers/gpu/drm/xe/xe_late_bind_fw.c
> +++ b/drivers/gpu/drm/xe/xe_late_bind_fw.c
> @@ -53,6 +53,32 @@ late_bind_fw_to_xe(struct xe_late_bind_fw *lb_fw)
>   	return container_of(lb_fw, struct xe_device, late_bind.late_bind_fw[lb_fw->id]);
>   }
>   
> +static const char *xe_late_bind_fw_status_to_str(enum xe_late_bind_fw_status status)
> +{
> +	switch (status) {
> +	case XE_LB_FW_NOT_SUPPORTED:
> +		return "Not Supported";
> +	case XE_LB_FW_AVAILABLE:
> +		return "Available";
> +	case XE_LB_FW_RUNNING:
> +		return "Running";
> +	case XE_LB_FW_FAILED:
> +		return "Failed";
> +	default:
> +		return "Unknown";
> +	}
> +}
> +
> +static void xe_late_bind_change_fw_status(struct xe_late_bind_fw *lb_fw,
> +					  enum xe_late_bind_fw_status status)
> +{
> +	struct xe_device *xe = late_bind_fw_to_xe(lb_fw);
> +
> +	lb_fw->__status = status;
> +	drm_dbg(&xe->drm, "%s firmware status changed to %s\n",
> +		fw_id_to_name[lb_fw->id], xe_late_bind_fw_status_to_str(status));
> +}
> +
>   /* Refer to the "Late Bind based Firmware Layout" documentation entry for details */
>   static int parse_cpd_header(struct xe_late_bind_fw *lb_fw,
>   			    const void *data, size_t size, const char *manifest_entry)
> @@ -235,6 +261,13 @@ static void xe_late_bind_wait_for_worker_completion(struct xe_late_bind *late_bi
>   			drm_dbg(&xe->drm, "Flush work: load %s firmware\n",
>   				fw_id_to_name[lbfw->id]);
>   			flush_work(&lbfw->work);
> +
> +			/*
> +			 * flush is being called during component unbind, suspend etc.
> +			 * So mark status XE_LB_FW_RUNNING -> XE_LB_FW_AVAILABLE
> +			 */
> +			if (lbfw->__status == XE_LB_FW_RUNNING)
> +				xe_late_bind_change_fw_status(lbfw, XE_LB_FW_AVAILABLE);

I am not convinced that this is the correct place for this. We might 
have cases in the future where we want to do a flush without clearing 
the state (e.g. before a reset).
Also, in the suspend scenario you're already adding xe_late_bind_fw_stop.

>   		}
>   	}
>   }
> @@ -282,6 +315,7 @@ static void xe_late_bind_work(struct work_struct *work)
>   	if (!ret) {
>   		drm_dbg(&xe->drm, "Load %s firmware successful\n",
>   			fw_id_to_name[lbfw->id]);
> +		xe_late_bind_change_fw_status(lbfw, XE_LB_FW_RUNNING);
>   		goto out;
>   	}
>   
> @@ -294,10 +328,23 @@ static void xe_late_bind_work(struct work_struct *work)
>   	/* Do not re-attempt fw load */
>   	drmm_kfree(&xe->drm, (void *)lbfw->payload);
>   	lbfw->payload = NULL;
> +	xe_late_bind_change_fw_status(lbfw, XE_LB_FW_FAILED);
>   out:
>   	xe_pm_runtime_put(xe);
>   }
>   
> +static void  xe_late_bind_fw_stop(struct xe_late_bind *late_bind)
> +{
> +	struct xe_late_bind_fw *lbfw;
> +	int fw_id;
> +
> +	for (fw_id = 0; fw_id < XE_LB_FW_MAX_ID; fw_id++) {
> +		lbfw = &late_bind->late_bind_fw[fw_id];
> +		if (lbfw->payload && lbfw->status == XE_LB_FW_RUNNING)
> +			xe_late_bind_change_fw_status(lbfw, XE_LB_FW_AVAILABLE);
> +	}
> +}
> +
>   static int xe_late_bind_fw_load(struct xe_late_bind *late_bind)
>   {
>   	struct xe_device *xe = late_bind_to_xe(late_bind);
> @@ -331,6 +378,7 @@ static int __xe_late_bind_fw_init(struct xe_late_bind *late_bind, u32 fw_id)
>   	lb_fw->id = fw_id;
>   	lb_fw->type = fw_id_to_type[lb_fw->id];
>   	lb_fw->flags &= ~INTEL_LB_FLAG_IS_PERSISTENT;
> +	xe_late_bind_change_fw_status(lb_fw, XE_LB_FW_NOT_SUPPORTED);
>   
>   	if (lb_fw->type == INTEL_LB_TYPE_FAN_CONTROL) {
>   		ret = xe_late_bind_fw_num_fans(late_bind, &num_fans);
> @@ -379,6 +427,7 @@ static int __xe_late_bind_fw_init(struct xe_late_bind *late_bind, u32 fw_id)
>   	memcpy((void *)lb_fw->payload, fw->data, lb_fw->payload_size);
>   	release_firmware(fw);
>   	INIT_WORK(&lb_fw->work, xe_late_bind_work);
> +	xe_late_bind_change_fw_status(lb_fw, XE_LB_FW_AVAILABLE);
>   
>   	return 0;
>   }
> @@ -445,15 +494,30 @@ static void xe_late_bind_remove(void *arg)
>   	}
>   }
>   
> -void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind)
> +/**
> + * xe_late_bind_ocode_status() - get ocode late bind firmware status
> + * @xe: pointer to xe device.
> + *
> + * Return: 0 if unsupported, 1 if available, 2 if running, 3 if failed.

This returns a value from xe_late_bind_fw_status, so might be worth just 
saying that.
also, you haven't defined the enum as starting from 0.

Daniele

> + */
> +int xe_late_bind_ocode_status(struct xe_device *xe)
> +{
> +	struct xe_late_bind_fw *lbfw = &xe->late_bind.late_bind_fw[XE_LB_FW_OCODE];
> +
> +	return lbfw->status;
> +}
> +
> +void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind, bool is_runtime)
>   {
>   	if (!late_bind->component_added)
>   		return;
>   
>   	if (late_bind->disable)
>   		return;
> +	if (!is_runtime)
> +		xe_late_bind_wait_for_worker_completion(late_bind);
>   
> -	xe_late_bind_wait_for_worker_completion(late_bind);
> +	xe_late_bind_fw_stop(late_bind);
>   }
>   
>   void xe_late_bind_pm_resume(struct xe_late_bind *late_bind)
> diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw.h b/drivers/gpu/drm/xe/xe_late_bind_fw.h
> index 8896fea3068e5..b441f5789f24b 100644
> --- a/drivers/gpu/drm/xe/xe_late_bind_fw.h
> +++ b/drivers/gpu/drm/xe/xe_late_bind_fw.h
> @@ -9,9 +9,10 @@
>   #include <linux/types.h>
>   
>   struct xe_late_bind;
> +struct xe_device;
>   
>   int xe_late_bind_init(struct xe_late_bind *late_bind);
> -void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind);
> +void xe_late_bind_pm_suspend(struct xe_late_bind *late_bind, bool is_runtime);
>   void xe_late_bind_pm_resume(struct xe_late_bind *late_bind);
> -
> +int xe_late_bind_ocode_status(struct xe_device *xe);
>   #endif
> diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
> index a128e3f638a6c..4cdbd775b103e 100644
> --- a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
> +++ b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
> @@ -26,6 +26,20 @@ enum xe_late_bind_fw_id {
>   	XE_LB_FW_MAX_ID
>   };
>   
> +/**
> + * enum xe_late_bind_fw_status - enum to determine late binding fw status
> + */
> +enum xe_late_bind_fw_status {
> +	/** @XE_LB_FW_NOT_SUPPORTED: firmware not available/supported */
> +	XE_LB_FW_NOT_SUPPORTED,
> +	/** @XE_LB_FW_AVAILABLE: firmware found and copied to memory */
> +	XE_LB_FW_AVAILABLE,
> +	/** @XE_LB_FW_RUNNING: firmware is running */
> +	XE_LB_FW_RUNNING,
> +	/** @XE_LB_FW_FAILED: firmware load is failed */
> +	XE_LB_FW_FAILED,
> +};
> +
>   /**
>    * struct xe_late_bind_fw
>    */
> @@ -46,6 +60,15 @@ struct xe_late_bind_fw {
>   	struct work_struct work;
>   	/** @version: late binding blob manifest version */
>   	struct gsc_version version;
> +	union {
> +		/** @status: firmware load status */
> +		const enum xe_late_bind_fw_status status;
> +		/**
> +		 * @__status: private firmware load status - only to be used
> +		 * by firmware loading code
> +		 */
> +		enum xe_late_bind_fw_status __status;
> +	};
>   };
>   
>   /**
> diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
> index f85b12c1a85d2..9aa873f57b5ad 100644
> --- a/drivers/gpu/drm/xe/xe_pm.c
> +++ b/drivers/gpu/drm/xe/xe_pm.c
> @@ -182,7 +182,7 @@ int xe_pm_suspend(struct xe_device *xe)
>   	if (err)
>   		goto err;
>   
> -	xe_late_bind_pm_suspend(&xe->late_bind);
> +	xe_late_bind_pm_suspend(&xe->late_bind, false);
>   
>   	for_each_gt(gt, xe, id)
>   		xe_gt_suspend_prepare(gt);
> @@ -612,6 +612,9 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
>   			goto out_resume;
>   	}
>   
> +	if (xe->d3cold.allowed)
> +		xe_late_bind_pm_suspend(&xe->late_bind, true);
> +
>   	xe_irq_suspend(xe);
>   
>   	xe_display_pm_runtime_suspend_late(xe);


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

* ✗ CI.KUnit: failure for Add ocode late binding support for CRI
  2026-03-05 10:44 [RFC PATCH 0/4] Add ocode late binding support for CRI Badal Nilawar
                   ` (3 preceding siblings ...)
  2026-03-05 10:44 ` [RFC PATCH 4/4] drm/xe/xe_late_bind_fw: Enable late binding support for CRI Badal Nilawar
@ 2026-03-06 11:26 ` Patchwork
  4 siblings, 0 replies; 9+ messages in thread
From: Patchwork @ 2026-03-06 11:26 UTC (permalink / raw)
  To: Badal Nilawar; +Cc: intel-xe

== Series Details ==

Series: Add ocode late binding support for CRI
URL   : https://patchwork.freedesktop.org/series/162657/
State : failure

== Summary ==

+ trap cleanup EXIT
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
ERROR:root:../drivers/gpu/drm/xe/xe_late_bind_fw.c:36:36: error: ‘INTEL_LB_TYPE_OCODE’ undeclared here (not in a function)
   36 |                 [XE_LB_FW_OCODE] = INTEL_LB_TYPE_OCODE,
      |                                    ^~~~~~~~~~~~~~~~~~~
../drivers/gpu/drm/xe/xe_late_bind_fw.c: In function ‘xe_late_bind_parse_status’:
../drivers/gpu/drm/xe/xe_late_bind_fw.c:210:14: error: ‘INTEL_LB_STATUS_INTERNAL_ERROR’ undeclared (first use in this function); did you mean ‘INTEL_LB_STATUS_GENERAL_ERROR’?
  210 |         case INTEL_LB_STATUS_INTERNAL_ERROR:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |              INTEL_LB_STATUS_GENERAL_ERROR
../drivers/gpu/drm/xe/xe_late_bind_fw.c:210:14: note: each undeclared identifier is reported only once for each function it appears in
../drivers/gpu/drm/xe/xe_late_bind_fw.c:212:14: error: ‘INTEL_LB_STATUS_INVALID_FPT_TABLE’ undeclared (first use in this function); did you mean ‘INTEL_LB_STATUS_INVALID_SIGNATURE’?
  212 |         case INTEL_LB_STATUS_INVALID_FPT_TABLE:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |              INTEL_LB_STATUS_INVALID_SIGNATURE
../drivers/gpu/drm/xe/xe_late_bind_fw.c:214:14: error: ‘INTEL_LB_STATUS_SIGNED_PAYLOAD_VERIFICATION_ERROR’ undeclared (first use in this function)
  214 |         case INTEL_LB_STATUS_SIGNED_PAYLOAD_VERIFICATION_ERROR:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/gpu/drm/xe/xe_late_bind_fw.c:216:14: error: ‘INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_CPD’ undeclared (first use in this function)
  216 |         case INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_CPD:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/gpu/drm/xe/xe_late_bind_fw.c:218:14: error: ‘INTEL_LB_STATUS_SIGNED_PAYLOAD_FW_VERSION_MISMATCH’ undeclared (first use in this function)
  218 |         case INTEL_LB_STATUS_SIGNED_PAYLOAD_FW_VERSION_MISMATCH:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/gpu/drm/xe/xe_late_bind_fw.c:220:14: error: ‘INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_MANIFEST’ undeclared (first use in this function)
  220 |         case INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_MANIFEST:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/gpu/drm/xe/xe_late_bind_fw.c:222:14: error: ‘INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_HASH’ undeclared (first use in this function)
  222 |         case INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_HASH:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/gpu/drm/xe/xe_late_bind_fw.c:224:14: error: ‘INTEL_LB_STATUS_SIGNED_PAYLOAD_BINDING_TYPE_MISMATCH’ undeclared (first use in this function)
  224 |         case INTEL_LB_STATUS_SIGNED_PAYLOAD_BINDING_TYPE_MISMATCH:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/gpu/drm/xe/xe_late_bind_fw.c:226:14: error: ‘INTEL_LB_STATUS_SIGNED_PAYLOAD_HANDLE_SVN_FAILED’ undeclared (first use in this function)
  226 |         case INTEL_LB_STATUS_SIGNED_PAYLOAD_HANDLE_SVN_FAILED:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/gpu/drm/xe/xe_late_bind_fw.c:228:14: error: ‘INTEL_LB_STATUS_DESTINATION_MBOX_FAILURE’ undeclared (first use in this function); did you mean ‘INTEL_LB_STATUS_ARB_FAILURE’?
  228 |         case INTEL_LB_STATUS_DESTINATION_MBOX_FAILURE:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |              INTEL_LB_STATUS_ARB_FAILURE
../drivers/gpu/drm/xe/xe_late_bind_fw.c:230:14: error: ‘INTEL_LB_STATUS_MISSING_LOADING_PATCH’ undeclared (first use in this function)
  230 |         case INTEL_LB_STATUS_MISSING_LOADING_PATCH:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/gpu/drm/xe/xe_late_bind_fw.c:232:14: error: ‘INTEL_LB_STATUS_INVALID_COMMAND’ undeclared (first use in this function); did you mean ‘INTEL_LB_STATUS_INVALID_PAYLOAD’?
  232 |         case INTEL_LB_STATUS_INVALID_COMMAND:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |              INTEL_LB_STATUS_INVALID_PAYLOAD
../drivers/gpu/drm/xe/xe_late_bind_fw.c:234:14: error: ‘INTEL_LB_STATUS_INVALID_HECI_HEADER’ undeclared (first use in this function); did you mean ‘INTEL_LB_STATUS_INVALID_PAYLOAD’?
  234 |         case INTEL_LB_STATUS_INVALID_HECI_HEADER:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |              INTEL_LB_STATUS_INVALID_PAYLOAD
../drivers/gpu/drm/xe/xe_late_bind_fw.c:236:14: error: ‘INTEL_LB_STATUS_IP_ERROR_START’ undeclared (first use in this function)
  236 |         case INTEL_LB_STATUS_IP_ERROR_START:
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
make[7]: *** [../scripts/Makefile.build:289: drivers/gpu/drm/xe/xe_late_bind_fw.o] Error 1
make[7]: *** Waiting for unfinished jobs....
make[6]: *** [../scripts/Makefile.build:546: drivers/gpu/drm/xe] Error 2
make[5]: *** [../scripts/Makefile.build:546: drivers/gpu/drm] Error 2
make[4]: *** [../scripts/Makefile.build:546: drivers/gpu] Error 2
make[3]: *** [../scripts/Makefile.build:546: drivers] Error 2
make[2]: *** [/kernel/Makefile:2101: .] Error 2
make[1]: *** [/kernel/Makefile:248: __sub-make] Error 2
make: *** [Makefile:248: __sub-make] Error 2

[11:26:10] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[11:26:15] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



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

end of thread, other threads:[~2026-03-06 11:26 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-05 10:44 [RFC PATCH 0/4] Add ocode late binding support for CRI Badal Nilawar
2026-03-05 10:44 ` [RFC PATCH 1/4] drm/xe/xe_late_bind_fw: Refactor pm flow Badal Nilawar
2026-03-05 14:20   ` Rodrigo Vivi
2026-03-05 10:44 ` [RFC PATCH 2/4] drm/xe/xe_late_bind_fw: Add support to load Ocode firmware on CRI Badal Nilawar
2026-03-05 23:38   ` Daniele Ceraolo Spurio
2026-03-05 10:44 ` [RFC PATCH 3/4] drm/xe/xe_late_bind_fw: Track firmware load status Badal Nilawar
2026-03-05 23:52   ` Daniele Ceraolo Spurio
2026-03-05 10:44 ` [RFC PATCH 4/4] drm/xe/xe_late_bind_fw: Enable late binding support for CRI Badal Nilawar
2026-03-06 11:26 ` ✗ CI.KUnit: failure for Add ocode " Patchwork

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox