drm/i915/mtl/gsc: query the GSC FW for its compatibility version

The compatibility version is queried via an MKHI command. Right now, the
only existing interface is 1.0
This is basically the interface version for the GSC FW, so the plan is
to use it as the main tracked version, including for the binary naming
in the fetch code.

v2: use define for the object size (Alan)
Signed-off-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Reviewed-by: default avatarAlan Previn <alan.previn.teres.alexis@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230612181529.2222451-4-daniele.ceraolospurio@intel.com
parent 56fafa56
......@@ -11,6 +11,7 @@
#include "gt/intel_ring.h"
#include "intel_gsc_binary_headers.h"
#include "intel_gsc_fw.h"
#include "intel_gsc_uc_heci_cmd_submit.h"
#define GSC_FW_STATUS_REG _MMIO(0x116C40)
#define GSC_FW_CURRENT_STATE REG_GENMASK(3, 0)
......@@ -303,6 +304,88 @@ static int gsc_fw_wait(struct intel_gt *gt)
500);
}
struct intel_gsc_mkhi_header {
u8 group_id;
#define MKHI_GROUP_ID_GFX_SRV 0x30
u8 command;
#define MKHI_GFX_SRV_GET_HOST_COMPATIBILITY_VERSION (0x42)
u8 reserved;
u8 result;
} __packed;
struct mtl_gsc_ver_msg_in {
struct intel_gsc_mtl_header header;
struct intel_gsc_mkhi_header mkhi;
} __packed;
struct mtl_gsc_ver_msg_out {
struct intel_gsc_mtl_header header;
struct intel_gsc_mkhi_header mkhi;
u16 proj_major;
u16 compat_major;
u16 compat_minor;
u16 reserved[5];
} __packed;
#define GSC_VER_PKT_SZ SZ_4K
static int gsc_fw_query_compatibility_version(struct intel_gsc_uc *gsc)
{
struct intel_gt *gt = gsc_uc_to_gt(gsc);
struct mtl_gsc_ver_msg_in *msg_in;
struct mtl_gsc_ver_msg_out *msg_out;
struct i915_vma *vma;
u64 offset;
void *vaddr;
int err;
err = intel_guc_allocate_and_map_vma(&gt->uc.guc, GSC_VER_PKT_SZ * 2,
&vma, &vaddr);
if (err) {
gt_err(gt, "failed to allocate vma for GSC version query\n");
return err;
}
offset = i915_ggtt_offset(vma);
msg_in = vaddr;
msg_out = vaddr + GSC_VER_PKT_SZ;
intel_gsc_uc_heci_cmd_emit_mtl_header(&msg_in->header,
HECI_MEADDRESS_MKHI,
sizeof(*msg_in), 0);
msg_in->mkhi.group_id = MKHI_GROUP_ID_GFX_SRV;
msg_in->mkhi.command = MKHI_GFX_SRV_GET_HOST_COMPATIBILITY_VERSION;
err = intel_gsc_uc_heci_cmd_submit_packet(&gt->uc.gsc,
offset,
sizeof(*msg_in),
offset + GSC_VER_PKT_SZ,
GSC_VER_PKT_SZ);
if (err) {
gt_err(gt,
"failed to submit GSC request for compatibility version: %d\n",
err);
goto out_vma;
}
if (msg_out->header.message_size != sizeof(*msg_out)) {
gt_err(gt, "invalid GSC reply length %u [expected %zu], s=0x%x, f=0x%x, r=0x%x\n",
msg_out->header.message_size, sizeof(*msg_out),
msg_out->header.status, msg_out->header.flags, msg_out->mkhi.result);
err = -EPROTO;
goto out_vma;
}
gsc->fw.file_selected.ver.major = msg_out->compat_major;
gsc->fw.file_selected.ver.minor = msg_out->compat_minor;
out_vma:
i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP);
return err;
}
int intel_gsc_uc_fw_upload(struct intel_gsc_uc *gsc)
{
struct intel_gt *gt = gsc_uc_to_gt(gsc);
......@@ -360,11 +443,21 @@ int intel_gsc_uc_fw_upload(struct intel_gsc_uc *gsc)
if (err)
goto fail;
err = gsc_fw_query_compatibility_version(gsc);
if (err)
goto fail;
/* we only support compatibility version 1.0 at the moment */
err = intel_uc_check_file_version(gsc_fw, NULL);
if (err)
goto fail;
/* FW is not fully operational until we enable SW proxy */
intel_uc_fw_change_status(gsc_fw, INTEL_UC_FIRMWARE_TRANSFERRED);
gt_info(gt, "Loaded GSC firmware %s (r%u.%u.%u.%u, svn%u)\n",
gt_info(gt, "Loaded GSC firmware %s (cv%u.%u, r%u.%u.%u.%u, svn %u)\n",
gsc_fw->file_selected.path,
gsc_fw->file_selected.ver.major, gsc_fw->file_selected.ver.minor,
gsc->release.major, gsc->release.minor,
gsc->release.patch, gsc->release.build,
gsc->security_version);
......
......@@ -17,6 +17,7 @@ struct intel_gsc_mtl_header {
#define GSC_HECI_VALIDITY_MARKER 0xA578875A
u8 heci_client_id;
#define HECI_MEADDRESS_MKHI 7
#define HECI_MEADDRESS_PROXY 10
#define HECI_MEADDRESS_PXP 17
#define HECI_MEADDRESS_HDCP 18
......
......@@ -787,6 +787,34 @@ static int try_firmware_load(struct intel_uc_fw *uc_fw, const struct firmware **
return 0;
}
int intel_uc_check_file_version(struct intel_uc_fw *uc_fw, bool *old_ver)
{
struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
struct intel_uc_fw_file *wanted = &uc_fw->file_wanted;
struct intel_uc_fw_file *selected = &uc_fw->file_selected;
if (!wanted->ver.major || !selected->ver.major)
return 0;
/* Check the file's major version was as it claimed */
if (selected->ver.major != wanted->ver.major) {
UNEXPECTED(gt, "%s firmware %s: unexpected version: %u.%u != %u.%u\n",
intel_uc_fw_type_repr(uc_fw->type), selected->path,
selected->ver.major, selected->ver.minor,
wanted->ver.major, wanted->ver.minor);
if (!intel_uc_fw_is_overridden(uc_fw))
return -ENOEXEC;
} else if (old_ver) {
if (selected->ver.minor < wanted->ver.minor)
*old_ver = true;
else if ((selected->ver.minor == wanted->ver.minor) &&
(selected->ver.patch < wanted->ver.patch))
*old_ver = true;
}
return 0;
}
/**
* intel_uc_fw_fetch - fetch uC firmware
* @uc_fw: uC firmware
......@@ -854,25 +882,9 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
goto fail;
}
if (uc_fw->file_wanted.ver.major && uc_fw->file_selected.ver.major) {
/* Check the file's major version was as it claimed */
if (uc_fw->file_selected.ver.major != uc_fw->file_wanted.ver.major) {
UNEXPECTED(gt, "%s firmware %s: unexpected version: %u.%u != %u.%u\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
uc_fw->file_selected.ver.major, uc_fw->file_selected.ver.minor,
uc_fw->file_wanted.ver.major, uc_fw->file_wanted.ver.minor);
if (!intel_uc_fw_is_overridden(uc_fw)) {
err = -ENOEXEC;
goto fail;
}
} else {
if (uc_fw->file_selected.ver.minor < uc_fw->file_wanted.ver.minor)
old_ver = true;
else if ((uc_fw->file_selected.ver.minor == uc_fw->file_wanted.ver.minor) &&
(uc_fw->file_selected.ver.patch < uc_fw->file_wanted.ver.patch))
old_ver = true;
}
}
err = intel_uc_check_file_version(uc_fw, &old_ver);
if (err)
goto fail;
if (old_ver && uc_fw->file_selected.ver.major) {
/* Preserve the version that was really wanted */
......
......@@ -292,6 +292,7 @@ static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw)
void intel_uc_fw_version_from_gsc_manifest(struct intel_uc_fw_ver *ver,
const void *data);
int intel_uc_check_file_version(struct intel_uc_fw *uc_fw, bool *old_ver);
void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
enum intel_uc_fw_type type,
bool needs_ggtt_mapping);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment