[Intel-xe] [PATCH v2 02/11] drm/xe/uc: Rework uC version tracking
John Harrison
john.c.harrison at intel.com
Thu Nov 16 22:38:23 UTC 2023
On 11/14/2023 16:46, Daniele Ceraolo Spurio wrote:
> The GSC firmware, support for which is coming soon for Xe, has both a
> release version (updated on every release) and a compatibility version
> (update only on interface changes). The GuC has something similar, with
> a global release version and a submission version (which is also known
> as the VF compatibility version). The main difference is that for the
> GuC we still want to check the driver requirement against the release
> version, while for the GSC we'll need to check against the compatibility
> version.
> Instead of special casing the GSC, this patch reworks the FW logic so
> that we store both versions at the uc_fw level for all binaries and we
> allow checking against either of the versions. Initially, we'll use it
> to support GSC, but the logic could be re-used to allow VFs to check
> against the GuC compatibility version.
> Note that the GSC version has 4 numbers (major, minor, hotfix, build),
> so support for that has been added as part of the rework and will be
> used in follow-up patches.
>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
> Cc: John Harrison <John.C.Harrison at Intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko at intel.com>
Reviewed-by: John Harrison <John.C.Harrison at Intel.com>
> ---
> drivers/gpu/drm/xe/xe_guc_types.h | 9 --
> drivers/gpu/drm/xe/xe_uc_fw.c | 141 +++++++++++++++++-----------
> drivers/gpu/drm/xe/xe_uc_fw_types.h | 35 +++++--
> 3 files changed, 110 insertions(+), 75 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_guc_types.h b/drivers/gpu/drm/xe/xe_guc_types.h
> index 0fdcc05dc16a..cd80802e8918 100644
> --- a/drivers/gpu/drm/xe/xe_guc_types.h
> +++ b/drivers/gpu/drm/xe/xe_guc_types.h
> @@ -52,15 +52,6 @@ struct xe_guc {
> /** @seqno: suspend fences seqno */
> u32 seqno;
> } suspend;
> - /** @version: submission version */
> - struct {
> - /** @major: major version of GuC submission */
> - u32 major;
> - /** @minor: minor version of GuC submission */
> - u32 minor;
> - /** @patch: patch version of GuC submission */
> - u32 patch;
> - } version;
> #ifdef CONFIG_PROVE_LOCKING
> #define NUM_SUBMIT_WQ 256
> /** @submit_wq_pool: submission ordered workqueues pool */
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
> index 91d4a2272ee7..9205a3ecff78 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw.c
> +++ b/drivers/gpu/drm/xe/xe_uc_fw.c
> @@ -204,9 +204,12 @@ uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw)
> for (i = 0; i < count && p <= entries[i].platform; i++) {
> if (p == entries[i].platform) {
> uc_fw->path = entries[i].path;
> - uc_fw->major_ver_wanted = entries[i].major;
> - uc_fw->minor_ver_wanted = entries[i].minor;
> + uc_fw->versions.wanted.major = entries[i].major;
> + uc_fw->versions.wanted.minor = entries[i].minor;
> uc_fw->full_ver_required = entries[i].full_ver_required;
> +
> + /* compatibility version checking coming soon */
> + uc_fw->versions.wanted_type = XE_UC_FW_VER_RELEASE;
> break;
> }
> }
> @@ -273,32 +276,30 @@ static void uc_fw_fini(struct drm_device *drm, void *arg)
> static void guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)
> {
> struct xe_gt *gt = uc_fw_to_gt(uc_fw);
> - struct xe_guc *guc = >->uc.guc;
> + struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
> + struct xe_uc_fw_version *compatibility = &uc_fw->versions.found[XE_UC_FW_VER_COMPATIBILITY];
>
> xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);
> - xe_gt_assert(gt, uc_fw->major_ver_found >= 70);
> + xe_gt_assert(gt, release->major >= 70);
>
> - if (uc_fw->major_ver_found > 70 || uc_fw->minor_ver_found >= 6) {
> + if (release->major > 70 || release->minor >= 6) {
> /* v70.6.0 adds CSS header support */
> - guc->submission_state.version.major =
> - FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
> - css->submission_version);
> - guc->submission_state.version.minor =
> - FIELD_GET(CSS_SW_VERSION_UC_MINOR,
> - css->submission_version);
> - guc->submission_state.version.patch =
> - FIELD_GET(CSS_SW_VERSION_UC_PATCH,
> - css->submission_version);
> - } else if (uc_fw->minor_ver_found >= 3) {
> + compatibility->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
> + css->submission_version);
> + compatibility->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR,
> + css->submission_version);
> + compatibility->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH,
> + css->submission_version);
> + } else if (release->minor >= 3) {
> /* v70.3.0 introduced v1.1.0 */
> - guc->submission_state.version.major = 1;
> - guc->submission_state.version.minor = 1;
> - guc->submission_state.version.patch = 0;
> + compatibility->major = 1;
> + compatibility->minor = 1;
> + compatibility->patch = 0;
> } else {
> /* v70.0.0 introduced v1.0.0 */
> - guc->submission_state.version.major = 1;
> - guc->submission_state.version.minor = 0;
> - guc->submission_state.version.patch = 0;
> + compatibility->major = 1;
> + compatibility->minor = 0;
> + compatibility->patch = 0;
> }
>
> uc_fw->private_data_size = css->private_data_size;
> @@ -307,30 +308,31 @@ static void guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)
> static int uc_fw_check_version_requirements(struct xe_uc_fw *uc_fw)
> {
> struct xe_device *xe = uc_fw_to_xe(uc_fw);
> + struct xe_uc_fw_version *wanted = &uc_fw->versions.wanted;
> + struct xe_uc_fw_version *found = &uc_fw->versions.found[uc_fw->versions.wanted_type];
>
> /* Driver has no requirement on any version, any is good. */
> - if (!uc_fw->major_ver_wanted)
> + if (!wanted->major)
> return 0;
>
> /*
> * If full version is required, both major and minor should match.
> * Otherwise, at least the major version.
> */
> - if (uc_fw->major_ver_wanted != uc_fw->major_ver_found ||
> - (uc_fw->full_ver_required &&
> - uc_fw->minor_ver_wanted != uc_fw->minor_ver_found)) {
> + if (wanted->major != found->major ||
> + (uc_fw->full_ver_required && wanted->minor != found->minor)) {
> drm_notice(&xe->drm, "%s firmware %s: unexpected version: %u.%u != %u.%u\n",
> xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
> - uc_fw->major_ver_found, uc_fw->minor_ver_found,
> - uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
> + found->major, found->minor,
> + wanted->major, wanted->minor);
> goto fail;
> }
>
> - if (uc_fw->minor_ver_wanted > uc_fw->minor_ver_found) {
> + if (wanted->minor > found->minor) {
> drm_notice(&xe->drm, "%s firmware (%u.%u) is recommended, but only (%u.%u) was found in %s\n",
> xe_uc_fw_type_repr(uc_fw->type),
> - uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted,
> - uc_fw->major_ver_found, uc_fw->minor_ver_found,
> + wanted->major, wanted->minor,
> + found->major, found->minor,
> uc_fw->path);
> drm_info(&xe->drm, "Consider updating your linux-firmware pkg or downloading from %s\n",
> XE_UC_FIRMWARE_URL);
> @@ -349,6 +351,7 @@ static int uc_fw_check_version_requirements(struct xe_uc_fw *uc_fw)
> static int parse_css_header(struct xe_uc_fw *uc_fw, const void *fw_data, size_t fw_size)
> {
> struct xe_device *xe = uc_fw_to_xe(uc_fw);
> + struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
> struct uc_css_header *css;
> size_t size;
>
> @@ -390,12 +393,9 @@ static int parse_css_header(struct xe_uc_fw *uc_fw, const void *fw_data, size_t
> }
>
> /* Get version numbers from the CSS header */
> - uc_fw->major_ver_found = FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
> - css->sw_version);
> - uc_fw->minor_ver_found = FIELD_GET(CSS_SW_VERSION_UC_MINOR,
> - css->sw_version);
> - uc_fw->patch_ver_found = FIELD_GET(CSS_SW_VERSION_UC_PATCH,
> - css->sw_version);
> + release->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR, css->sw_version);
> + release->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR, css->sw_version);
> + release->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH, css->sw_version);
>
> if (uc_fw->type == XE_UC_FW_TYPE_GUC)
> guc_read_css_info(uc_fw, css);
> @@ -431,6 +431,7 @@ static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t siz
> struct xe_gt *gt = uc_fw_to_gt(uc_fw);
> struct xe_device *xe = gt_to_xe(gt);
> const struct gsc_cpd_header_v2 *header = data;
> + struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
> const struct gsc_manifest_header *manifest;
> size_t min_size = sizeof(*header);
> u32 offset;
> @@ -468,9 +469,9 @@ static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t siz
>
> manifest = data + offset;
>
> - uc_fw->major_ver_found = manifest->fw_version.major;
> - uc_fw->minor_ver_found = manifest->fw_version.minor;
> - uc_fw->patch_ver_found = manifest->fw_version.hotfix;
> + release->major = manifest->fw_version.major;
> + release->minor = manifest->fw_version.minor;
> + release->patch = manifest->fw_version.hotfix;
>
> /* then optionally look for the css header */
> if (css_entry) {
> @@ -524,12 +525,25 @@ static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)
> return 0;
> }
>
> +#define print_uc_fw_version(p_, version_, prefix_, ...) \
> +do { \
> + struct xe_uc_fw_version *ver_ = (version_); \
> + if (ver_->build) \
> + drm_printf(p_, prefix_ " version %u.%u.%u.%u\n", ##__VA_ARGS__, \
> + ver_->major, ver_->minor, \
> + ver_->patch, ver_->build); \
> + else \
> + drm_printf(p_, prefix_ " version %u.%u.%u\n", ##__VA_ARGS__, \
> + ver_->major, ver_->minor, ver_->patch); \
> +} while (0)
> +
> int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
> {
> struct xe_device *xe = uc_fw_to_xe(uc_fw);
> struct xe_gt *gt = uc_fw_to_gt(uc_fw);
> struct xe_tile *tile = gt_to_tile(gt);
> struct device *dev = xe->drm.dev;
> + struct drm_printer p = drm_info_printer(dev);
> const struct firmware *fw = NULL;
> struct xe_bo *obj;
> int err;
> @@ -567,9 +581,10 @@ int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
> if (err)
> goto fail;
>
> - drm_info(&xe->drm, "Using %s firmware from %s version %u.%u.%u\n",
> - xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
> - uc_fw->major_ver_found, uc_fw->minor_ver_found, uc_fw->patch_ver_found);
> + print_uc_fw_version(&p,
> + &uc_fw->versions.found[XE_UC_FW_VER_RELEASE],
> + "Using %s firmware from %s",
> + xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
>
> err = uc_fw_check_version_requirements(uc_fw);
> if (err)
> @@ -686,26 +701,40 @@ int xe_uc_fw_upload(struct xe_uc_fw *uc_fw, u32 offset, u32 dma_flags)
> return err;
> }
>
> +static const char *version_type_repr(enum xe_uc_fw_version_types type)
> +{
> + switch (type) {
> + case XE_UC_FW_VER_RELEASE:
> + return "release";
> + case XE_UC_FW_VER_COMPATIBILITY:
> + return "compatibility";
> + default:
> + return "Unknown version type";
> + }
> +}
>
> void xe_uc_fw_print(struct xe_uc_fw *uc_fw, struct drm_printer *p)
> {
> + int i;
> +
> drm_printf(p, "%s firmware: %s\n",
> xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
> drm_printf(p, "\tstatus: %s\n",
> xe_uc_fw_status_repr(uc_fw->status));
> - drm_printf(p, "\tversion: wanted %u.%u, found %u.%u.%u\n",
> - uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted,
> - uc_fw->major_ver_found, uc_fw->minor_ver_found, uc_fw->patch_ver_found);
> - drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);
> - drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);
> -
> - if (uc_fw->type == XE_UC_FW_TYPE_GUC) {
> - struct xe_gt *gt = uc_fw_to_gt(uc_fw);
> - struct xe_guc *guc = >->uc.guc;
> -
> - drm_printf(p, "\tSubmit version: %u.%u.%u\n",
> - guc->submission_state.version.major,
> - guc->submission_state.version.minor,
> - guc->submission_state.version.patch);
> +
> + print_uc_fw_version(p, &uc_fw->versions.wanted, "\twanted %s",
> + version_type_repr(uc_fw->versions.wanted_type));
> +
> + for (i = 0; i < XE_UC_FW_VER_TYPE_COUNT; i++) {
> + struct xe_uc_fw_version *ver = &uc_fw->versions.found[i];
> +
> + if (ver->major)
> + print_uc_fw_version(p, ver, "\tfound %s",
> + version_type_repr(i));
> }
> +
> + if (uc_fw->ucode_size)
> + drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);
> + if (uc_fw->rsa_size)
> + drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);
> }
> diff --git a/drivers/gpu/drm/xe/xe_uc_fw_types.h b/drivers/gpu/drm/xe/xe_uc_fw_types.h
> index 1650599303c8..e4774c560e67 100644
> --- a/drivers/gpu/drm/xe/xe_uc_fw_types.h
> +++ b/drivers/gpu/drm/xe/xe_uc_fw_types.h
> @@ -59,6 +59,22 @@ enum xe_uc_fw_type {
> };
> #define XE_UC_FW_NUM_TYPES 2
>
> +/**
> + * struct xe_uc_fw_version - Version for XE micro controller firmware
> + */
> +struct xe_uc_fw_version {
> + u16 major;
> + u16 minor;
> + u16 patch;
> + u16 build;
> +};
> +
> +enum xe_uc_fw_version_types {
> + XE_UC_FW_VER_RELEASE,
> + XE_UC_FW_VER_COMPATIBILITY,
> + XE_UC_FW_VER_TYPE_COUNT
> +};
> +
> /**
> * struct xe_uc_fw - XE micro controller firmware
> */
> @@ -98,16 +114,15 @@ struct xe_uc_fw {
> * version required per platform.
> */
>
> - /** @major_ver_wanted: major firmware version wanted by platform */
> - u16 major_ver_wanted;
> - /** @minor_ver_wanted: minor firmware version wanted by platform */
> - u16 minor_ver_wanted;
> - /** @major_ver_found: major version found in firmware blob */
> - u16 major_ver_found;
> - /** @minor_ver_found: major version found in firmware blob */
> - u16 minor_ver_found;
> - /** @patch_ver_found: patch version found in firmware blob */
> - u16 patch_ver_found;
> + /** @versions: FW versions wanted and found */
> + struct {
> + /** @wanted: firmware version wanted by platform */
> + struct xe_uc_fw_version wanted;
> + /** @wanted_type: type of firmware version wanted (release vs compatibility) */
> + enum xe_uc_fw_version_types wanted_type;
> + /** @found: fw versions found in firmware blob */
> + struct xe_uc_fw_version found[XE_UC_FW_VER_TYPE_COUNT];
> + } versions;
>
> /** @rsa_size: RSA size */
> u32 rsa_size;
More information about the Intel-xe
mailing list