* [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