]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
drm/xe/uc: Prepare for parsing of different header types
authorDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Wed, 25 Oct 2023 17:57:41 +0000 (10:57 -0700)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Thu, 21 Dec 2023 16:43:22 +0000 (11:43 -0500)
GSC binaries and newer HuC ones use GSC-style headers instead of the
CSS. In preparation for adding support for such parsing, split out the
current parsing code to its own function, to make it cleaner to add the
new paths. The existing doc section has also been renamed to narrow it
to CSS-based binaries.

v2: new patch in series, split out from next patch for easier reviewing
v3: drop unneeded include (Lucas)

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Documentation/gpu/xe/xe_firmware.rst
drivers/gpu/drm/xe/xe_uc_fw.c
drivers/gpu/drm/xe/xe_uc_fw_abi.h

index c01246ae99f539cc14ce8b708af50cfaacb25572..f1ac6f60893052417d00179769200b7b24f60ec0 100644 (file)
@@ -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
 ==================================================
index 32782a52c07f7ea293da239e2fa7fc41a836531d..189a298e54790e5673a8d45319886752fb81aaea 100644 (file)
@@ -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) |
index 89e994ed4e0095408d338df78fd67445767545f6..edae7bb3cd7203c3d364a2f1a9938e8efbbede2b 100644 (file)
 #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                                                       |