Commit 665ae9c9 authored by John Harrison's avatar John Harrison Committed by Daniele Ceraolo Spurio

drm/i915/uc: Support for version reduced and multiple firmware files

There was a misunderstanding in how firmware file compatibility should
be managed within i915. This has been clarified as:
  i915 must support all existing firmware releases forever
  new minor firmware releases should replace prior versions
  only backwards compatibility breaking releases should be a new file

This patch cleans up the single fallback file support that was added
as a quick fix emergency effort. That is now removed in preference to
supporting arbitrary numbers of firmware files per platform.

The patch also adds support for having GuC firmware files that are
named by major version only (because the major version indicates
backwards breaking changes that affect the KMD) and for having HuC
firmware files with no version number at all (because the KMD has no
interface requirements with the HuC).

For GuC, the driver will report via dmesg if the found file is older than
expected. For HuC, the KMD will no longer require updating for any new
HuC release so will not be able to report what the latest expected
version is.
Signed-off-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Reviewed-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Signed-off-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220906230147.479945-1-daniele.ceraolospurio@intel.com
parent 68eb42b3
...@@ -1868,7 +1868,7 @@ int intel_guc_submission_init(struct intel_guc *guc) ...@@ -1868,7 +1868,7 @@ int intel_guc_submission_init(struct intel_guc *guc)
if (guc->submission_initialized) if (guc->submission_initialized)
return 0; return 0;
if (guc->fw.major_ver_found < 70) { if (guc->fw.file_selected.major_ver < 70) {
ret = guc_lrc_desc_pool_create_v69(guc); ret = guc_lrc_desc_pool_create_v69(guc);
if (ret) if (ret)
return ret; return ret;
...@@ -2303,7 +2303,7 @@ static int register_context(struct intel_context *ce, bool loop) ...@@ -2303,7 +2303,7 @@ static int register_context(struct intel_context *ce, bool loop)
GEM_BUG_ON(intel_context_is_child(ce)); GEM_BUG_ON(intel_context_is_child(ce));
trace_intel_context_register(ce); trace_intel_context_register(ce);
if (guc->fw.major_ver_found >= 70) if (guc->fw.file_selected.major_ver >= 70)
ret = register_context_v70(guc, ce, loop); ret = register_context_v70(guc, ce, loop);
else else
ret = register_context_v69(guc, ce, loop); ret = register_context_v69(guc, ce, loop);
...@@ -2315,7 +2315,7 @@ static int register_context(struct intel_context *ce, bool loop) ...@@ -2315,7 +2315,7 @@ static int register_context(struct intel_context *ce, bool loop)
set_context_registered(ce); set_context_registered(ce);
spin_unlock_irqrestore(&ce->guc_state.lock, flags); spin_unlock_irqrestore(&ce->guc_state.lock, flags);
if (guc->fw.major_ver_found >= 70) if (guc->fw.file_selected.major_ver >= 70)
guc_context_policy_init_v70(ce, loop); guc_context_policy_init_v70(ce, loop);
} }
...@@ -2921,7 +2921,7 @@ static void __guc_context_set_preemption_timeout(struct intel_guc *guc, ...@@ -2921,7 +2921,7 @@ static void __guc_context_set_preemption_timeout(struct intel_guc *guc,
u16 guc_id, u16 guc_id,
u32 preemption_timeout) u32 preemption_timeout)
{ {
if (guc->fw.major_ver_found >= 70) { if (guc->fw.file_selected.major_ver >= 70) {
struct context_policy policy; struct context_policy policy;
__guc_context_policy_start_klv(&policy, guc_id); __guc_context_policy_start_klv(&policy, guc_id);
...@@ -3186,7 +3186,7 @@ static int guc_context_alloc(struct intel_context *ce) ...@@ -3186,7 +3186,7 @@ static int guc_context_alloc(struct intel_context *ce)
static void __guc_context_set_prio(struct intel_guc *guc, static void __guc_context_set_prio(struct intel_guc *guc,
struct intel_context *ce) struct intel_context *ce)
{ {
if (guc->fw.major_ver_found >= 70) { if (guc->fw.file_selected.major_ver >= 70) {
struct context_policy policy; struct context_policy policy;
__guc_context_policy_start_klv(&policy, ce->guc_id.id); __guc_context_policy_start_klv(&policy, ce->guc_id.id);
......
...@@ -436,8 +436,8 @@ static void print_fw_ver(struct intel_uc *uc, struct intel_uc_fw *fw) ...@@ -436,8 +436,8 @@ static void print_fw_ver(struct intel_uc *uc, struct intel_uc_fw *fw)
struct drm_i915_private *i915 = uc_to_gt(uc)->i915; struct drm_i915_private *i915 = uc_to_gt(uc)->i915;
drm_info(&i915->drm, "%s firmware %s version %u.%u\n", drm_info(&i915->drm, "%s firmware %s version %u.%u\n",
intel_uc_fw_type_repr(fw->type), fw->path, intel_uc_fw_type_repr(fw->type), fw->file_selected.path,
fw->major_ver_found, fw->minor_ver_found); fw->file_selected.major_ver, fw->file_selected.minor_ver);
} }
static int __uc_init_hw(struct intel_uc *uc) static int __uc_init_hw(struct intel_uc *uc)
......
This diff is collapsed.
...@@ -64,6 +64,17 @@ enum intel_uc_fw_type { ...@@ -64,6 +64,17 @@ enum intel_uc_fw_type {
}; };
#define INTEL_UC_FW_NUM_TYPES 2 #define INTEL_UC_FW_NUM_TYPES 2
/*
* The firmware build process will generate a version header file with major and
* minor version defined. The versions are built into CSS header of firmware.
* i915 kernel driver set the minimal firmware version required per platform.
*/
struct intel_uc_fw_file {
const char *path;
u16 major_ver;
u16 minor_ver;
};
/* /*
* This structure encapsulates all the data needed during the process * This structure encapsulates all the data needed during the process
* of fetching, caching, and loading the firmware image into the uC. * of fetching, caching, and loading the firmware image into the uC.
...@@ -74,11 +85,12 @@ struct intel_uc_fw { ...@@ -74,11 +85,12 @@ struct intel_uc_fw {
const enum intel_uc_fw_status status; const enum intel_uc_fw_status status;
enum intel_uc_fw_status __status; /* no accidental overwrites */ enum intel_uc_fw_status __status; /* no accidental overwrites */
}; };
const char *wanted_path; struct intel_uc_fw_file file_wanted;
const char *path; struct intel_uc_fw_file file_selected;
bool user_overridden; bool user_overridden;
size_t size; size_t size;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
/** /**
* @dummy: A vma used in binding the uc fw to ggtt. We can't define this * @dummy: A vma used in binding the uc fw to ggtt. We can't define this
* vma on the stack as it can lead to a stack overflow, so we define it * vma on the stack as it can lead to a stack overflow, so we define it
...@@ -89,25 +101,8 @@ struct intel_uc_fw { ...@@ -89,25 +101,8 @@ struct intel_uc_fw {
struct i915_vma_resource dummy; struct i915_vma_resource dummy;
struct i915_vma *rsa_data; struct i915_vma *rsa_data;
/*
* The firmware build process will generate a version header file with major and
* minor version defined. The versions are built into CSS header of firmware.
* i915 kernel driver set the minimal firmware version required per platform.
*/
u16 major_ver_wanted;
u16 minor_ver_wanted;
u16 major_ver_found;
u16 minor_ver_found;
struct {
const char *path;
u16 major_ver;
u16 minor_ver;
} fallback;
u32 rsa_size; u32 rsa_size;
u32 ucode_size; u32 ucode_size;
u32 private_data_size; u32 private_data_size;
bool loaded_via_gsc; bool loaded_via_gsc;
......
...@@ -1023,8 +1023,10 @@ static void cleanup_params(struct i915_gpu_coredump *error) ...@@ -1023,8 +1023,10 @@ static void cleanup_params(struct i915_gpu_coredump *error)
static void cleanup_uc(struct intel_uc_coredump *uc) static void cleanup_uc(struct intel_uc_coredump *uc)
{ {
kfree(uc->guc_fw.path); kfree(uc->guc_fw.file_selected.path);
kfree(uc->huc_fw.path); kfree(uc->huc_fw.file_selected.path);
kfree(uc->guc_fw.file_wanted.path);
kfree(uc->huc_fw.file_wanted.path);
i915_vma_coredump_free(uc->guc.vma_log); i915_vma_coredump_free(uc->guc.vma_log);
i915_vma_coredump_free(uc->guc.vma_ctb); i915_vma_coredump_free(uc->guc.vma_ctb);
...@@ -1706,12 +1708,10 @@ gt_record_uc(struct intel_gt_coredump *gt, ...@@ -1706,12 +1708,10 @@ gt_record_uc(struct intel_gt_coredump *gt,
memcpy(&error_uc->guc_fw, &uc->guc.fw, sizeof(uc->guc.fw)); memcpy(&error_uc->guc_fw, &uc->guc.fw, sizeof(uc->guc.fw));
memcpy(&error_uc->huc_fw, &uc->huc.fw, sizeof(uc->huc.fw)); memcpy(&error_uc->huc_fw, &uc->huc.fw, sizeof(uc->huc.fw));
/* Non-default firmware paths will be specified by the modparam. error_uc->guc_fw.file_selected.path = kstrdup(uc->guc.fw.file_selected.path, ALLOW_FAIL);
* As modparams are generally accesible from the userspace make error_uc->huc_fw.file_selected.path = kstrdup(uc->huc.fw.file_selected.path, ALLOW_FAIL);
* explicit copies of the firmware paths. error_uc->guc_fw.file_wanted.path = kstrdup(uc->guc.fw.file_wanted.path, ALLOW_FAIL);
*/ error_uc->huc_fw.file_wanted.path = kstrdup(uc->huc.fw.file_wanted.path, ALLOW_FAIL);
error_uc->guc_fw.path = kstrdup(uc->guc.fw.path, ALLOW_FAIL);
error_uc->huc_fw.path = kstrdup(uc->huc.fw.path, ALLOW_FAIL);
/* /*
* Save the GuC log and include a timestamp reference for converting the * Save the GuC log and include a timestamp reference for converting the
......
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