summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/gpu/xe/xe_firmware.rst2
-rw-r--r--drivers/gpu/drm/xe/xe_uc_fw.c116
-rw-r--r--drivers/gpu/drm/xe/xe_uc_fw_abi.h7
3 files changed, 71 insertions, 54 deletions
diff --git a/Documentation/gpu/xe/xe_firmware.rst b/Documentation/gpu/xe/xe_firmware.rst
index c01246ae99f5..f1ac6f608930 100644
--- a/Documentation/gpu/xe/xe_firmware.rst
+++ b/Documentation/gpu/xe/xe_firmware.rst
@@ -8,7 +8,7 @@ Firmware Layout
===============
.. kernel-doc:: drivers/gpu/drm/xe/xe_uc_fw_abi.h
- :doc: Firmware Layout
+ :doc: CSS-based Firmware Layout
Write Once Protected Content Memory (WOPCM) Layout
==================================================
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
index 32782a52c07f..189a298e5479 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.c
+++ b/drivers/gpu/drm/xe/xe_uc_fw.c
@@ -344,57 +344,22 @@ fail:
return -ENOEXEC;
}
-int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
+/* Refer to the "CSS-based Firmware Layout" documentation entry for details */
+static int parse_css_header(struct xe_uc_fw *uc_fw, const void *fw_data, size_t fw_size)
{
struct xe_device *xe = uc_fw_to_xe(uc_fw);
- struct xe_gt *gt = uc_fw_to_gt(uc_fw);
- struct xe_tile *tile = gt_to_tile(gt);
- struct device *dev = xe->drm.dev;
- const struct firmware *fw = NULL;
struct uc_css_header *css;
- struct xe_bo *obj;
size_t size;
- int err;
-
- /*
- * we use FIRMWARE_UNINITIALIZED to detect checks against uc_fw->status
- * before we're looked at the HW caps to see if we have uc support
- */
- BUILD_BUG_ON(XE_UC_FIRMWARE_UNINITIALIZED);
- xe_assert(xe, !uc_fw->status);
- xe_assert(xe, !uc_fw->path);
-
- uc_fw_auto_select(xe, uc_fw);
- xe_uc_fw_change_status(uc_fw, uc_fw->path ?
- XE_UC_FIRMWARE_SELECTED :
- XE_UC_FIRMWARE_NOT_SUPPORTED);
-
- if (!xe_uc_fw_is_supported(uc_fw))
- return 0;
-
- uc_fw_override(uc_fw);
-
- /* an empty path means the firmware is disabled */
- if (!xe_device_uc_enabled(xe) || !(*uc_fw->path)) {
- xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_DISABLED);
- drm_dbg(&xe->drm, "%s disabled", xe_uc_fw_type_repr(uc_fw->type));
- return 0;
- }
-
- err = request_firmware(&fw, uc_fw->path, dev);
- if (err)
- goto fail;
/* Check the size of the blob before examining buffer contents */
- if (unlikely(fw->size < sizeof(struct uc_css_header))) {
+ if (unlikely(fw_size < sizeof(struct uc_css_header))) {
drm_warn(&xe->drm, "%s firmware %s: invalid size: %zu < %zu\n",
xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
- fw->size, sizeof(struct uc_css_header));
- err = -ENODATA;
- goto fail;
+ fw_size, sizeof(struct uc_css_header));
+ return -ENODATA;
}
- css = (struct uc_css_header *)fw->data;
+ css = (struct uc_css_header *)fw_data;
/* Check integrity of size values inside CSS header */
size = (css->header_size_dw - css->key_size_dw - css->modulus_size_dw -
@@ -403,9 +368,8 @@ int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
drm_warn(&xe->drm,
"%s firmware %s: unexpected header size: %zu != %zu\n",
xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
- fw->size, sizeof(struct uc_css_header));
- err = -EPROTO;
- goto fail;
+ fw_size, sizeof(struct uc_css_header));
+ return -EPROTO;
}
/* uCode size must calculated from other sizes */
@@ -417,12 +381,11 @@ int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
/* At least, it should have header, uCode and RSA. Size of all three. */
size = sizeof(struct uc_css_header) + uc_fw->ucode_size +
uc_fw->rsa_size;
- if (unlikely(fw->size < size)) {
+ if (unlikely(fw_size < size)) {
drm_warn(&xe->drm, "%s firmware %s: invalid size: %zu < %zu\n",
xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
- fw->size, size);
- err = -ENOEXEC;
- goto fail;
+ fw_size, size);
+ return -ENOEXEC;
}
/* Get version numbers from the CSS header */
@@ -433,6 +396,60 @@ int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
uc_fw->patch_ver_found = FIELD_GET(CSS_SW_VERSION_UC_PATCH,
css->sw_version);
+ if (uc_fw->type == XE_UC_FW_TYPE_GUC)
+ guc_read_css_info(uc_fw, css);
+
+ return 0;
+}
+
+static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)
+{
+ return parse_css_header(uc_fw, fw->data, fw->size);
+}
+
+int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
+{
+ struct xe_device *xe = uc_fw_to_xe(uc_fw);
+ struct xe_gt *gt = uc_fw_to_gt(uc_fw);
+ struct xe_tile *tile = gt_to_tile(gt);
+ struct device *dev = xe->drm.dev;
+ const struct firmware *fw = NULL;
+ struct xe_bo *obj;
+ int err;
+
+ /*
+ * we use FIRMWARE_UNINITIALIZED to detect checks against uc_fw->status
+ * before we're looked at the HW caps to see if we have uc support
+ */
+ BUILD_BUG_ON(XE_UC_FIRMWARE_UNINITIALIZED);
+ xe_assert(xe, !uc_fw->status);
+ xe_assert(xe, !uc_fw->path);
+
+ uc_fw_auto_select(xe, uc_fw);
+ xe_uc_fw_change_status(uc_fw, uc_fw->path ?
+ XE_UC_FIRMWARE_SELECTED :
+ XE_UC_FIRMWARE_NOT_SUPPORTED);
+
+ if (!xe_uc_fw_is_supported(uc_fw))
+ return 0;
+
+ uc_fw_override(uc_fw);
+
+ /* an empty path means the firmware is disabled */
+ if (!xe_device_uc_enabled(xe) || !(*uc_fw->path)) {
+ xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_DISABLED);
+ drm_dbg(&xe->drm, "%s disabled", xe_uc_fw_type_repr(uc_fw->type));
+ return 0;
+ }
+
+ err = request_firmware(&fw, uc_fw->path, dev);
+ if (err)
+ goto fail;
+
+ err = parse_headers(uc_fw, fw);
+ if (err)
+ goto fail;
+
drm_info(&xe->drm, "Using %s firmware from %s version %u.%u.%u\n",
xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
uc_fw->major_ver_found, uc_fw->minor_ver_found, uc_fw->patch_ver_found);
@@ -441,9 +458,6 @@ int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
if (err)
goto fail;
- if (uc_fw->type == XE_UC_FW_TYPE_GUC)
- guc_read_css_info(uc_fw, css);
-
obj = xe_bo_create_from_data(xe, tile, fw->data, fw->size,
ttm_bo_type_kernel,
XE_BO_CREATE_VRAM_IF_DGFX(tile) |
diff --git a/drivers/gpu/drm/xe/xe_uc_fw_abi.h b/drivers/gpu/drm/xe/xe_uc_fw_abi.h
index 89e994ed4e00..edae7bb3cd72 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw_abi.h
+++ b/drivers/gpu/drm/xe/xe_uc_fw_abi.h
@@ -10,9 +10,12 @@
#include <linux/types.h>
/**
- * DOC: Firmware Layout
+ * DOC: CSS-based Firmware Layout
*
- * The GuC/HuC firmware layout looks like this::
+ * The CSS-based firmware structure is used for GuC releases on all platforms
+ * and for HuC releases up to DG1. Starting from DG2/MTL the HuC uses the GSC
+ * layout instead.
+ * The CSS firmware layout looks like this::
*
* +======================================================================+
* | Firmware blob |