Skip to content

Commit 6a9b6c4

Browse files
committed
drm/i915/huc: Load GSC-enabled HuC via DMA xfer if the fuse says so
In the previous patch we extracted the offset of the legacy-style HuC binary located within the GSC-enabled blob, so now we can use that to load the HuC via DMA if the fuse is set that way. Note that we now need to differentiate between "GSC-enabled binary" and "loaded by GSC", so the former case has been renamed to "has GSC headers" for clarity, while the latter is now based on the fuse instead of the binary format. This way, all the legacy load paths are automatically taken (including the auth by GuC) without having to implement further code changes. v2: s/is_meu_binary/has_gsc_headers/, clearer logs (John) v3: split check for GSC access, better comments (John) 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> Reviewed-by: John Harrison <John.C.Harrison@Intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230531235415.1467475-4-daniele.ceraolospurio@intel.com
1 parent 93a575a commit 6a9b6c4

5 files changed

Lines changed: 47 additions & 22 deletions

File tree

drivers/gpu/drm/i915/gt/uc/intel_huc.c

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -298,31 +298,54 @@ void intel_huc_init_early(struct intel_huc *huc)
298298
static int check_huc_loading_mode(struct intel_huc *huc)
299299
{
300300
struct intel_gt *gt = huc_to_gt(huc);
301-
bool fw_needs_gsc = intel_huc_is_loaded_by_gsc(huc);
302-
bool hw_uses_gsc = false;
301+
bool gsc_enabled = huc->fw.has_gsc_headers;
303302

304303
/*
305304
* The fuse for HuC load via GSC is only valid on platforms that have
306305
* GuC deprivilege.
307306
*/
308307
if (HAS_GUC_DEPRIVILEGE(gt->i915))
309-
hw_uses_gsc = intel_uncore_read(gt->uncore, GUC_SHIM_CONTROL2) &
310-
GSC_LOADS_HUC;
308+
huc->loaded_via_gsc = intel_uncore_read(gt->uncore, GUC_SHIM_CONTROL2) &
309+
GSC_LOADS_HUC;
311310

312-
if (fw_needs_gsc != hw_uses_gsc) {
313-
huc_err(huc, "mismatch between FW (%s) and HW (%s) load modes\n",
314-
HUC_LOAD_MODE_STRING(fw_needs_gsc), HUC_LOAD_MODE_STRING(hw_uses_gsc));
311+
if (huc->loaded_via_gsc && !gsc_enabled) {
312+
huc_err(huc, "HW requires a GSC-enabled blob, but we found a legacy one\n");
315313
return -ENOEXEC;
316314
}
317315

318-
/* make sure we can access the GSC via the mei driver if we need it */
319-
if (!(IS_ENABLED(CONFIG_INTEL_MEI_PXP) && IS_ENABLED(CONFIG_INTEL_MEI_GSC)) &&
320-
fw_needs_gsc) {
321-
huc_info(huc, "can't load due to missing MEI modules\n");
322-
return -EIO;
316+
/*
317+
* On newer platforms we have GSC-enabled binaries but we load the HuC
318+
* via DMA. To do so we need to find the location of the legacy-style
319+
* binary inside the GSC-enabled one, which we do at fetch time. Make
320+
* sure that we were able to do so if the fuse says we need to load via
321+
* DMA and the binary is GSC-enabled.
322+
*/
323+
if (!huc->loaded_via_gsc && gsc_enabled && !huc->fw.dma_start_offset) {
324+
huc_err(huc, "HW in DMA mode, but we have an incompatible GSC-enabled blob\n");
325+
return -ENOEXEC;
326+
}
327+
328+
/*
329+
* If the HuC is loaded via GSC, we need to be able to access the GSC.
330+
* On DG2 this is done via the mei components, while on newer platforms
331+
* it is done via the GSCCS,
332+
*/
333+
if (huc->loaded_via_gsc) {
334+
if (IS_DG2(gt->i915)) {
335+
if (!IS_ENABLED(CONFIG_INTEL_MEI_PXP) ||
336+
!IS_ENABLED(CONFIG_INTEL_MEI_GSC)) {
337+
huc_info(huc, "can't load due to missing mei modules\n");
338+
return -EIO;
339+
}
340+
} else {
341+
if (!HAS_ENGINE(gt, GSC0)) {
342+
huc_info(huc, "can't load due to missing GSCCS\n");
343+
return -EIO;
344+
}
345+
}
323346
}
324347

325-
huc_dbg(huc, "loaded by GSC = %s\n", str_yes_no(fw_needs_gsc));
348+
huc_dbg(huc, "loaded by GSC = %s\n", str_yes_no(huc->loaded_via_gsc));
326349

327350
return 0;
328351
}

drivers/gpu/drm/i915/gt/uc/intel_huc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ struct intel_huc {
3939
struct notifier_block nb;
4040
enum intel_huc_delayed_load_status status;
4141
} delayed_load;
42+
43+
bool loaded_via_gsc;
4244
};
4345

4446
int intel_huc_sanitize(struct intel_huc *huc);
@@ -73,7 +75,7 @@ static inline bool intel_huc_is_used(struct intel_huc *huc)
7375

7476
static inline bool intel_huc_is_loaded_by_gsc(const struct intel_huc *huc)
7577
{
76-
return huc->fw.loaded_via_gsc;
78+
return huc->loaded_via_gsc;
7779
}
7880

7981
static inline bool intel_huc_wait_required(struct intel_huc *huc)

drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ int intel_huc_fw_get_binary_info(struct intel_uc_fw *huc_fw, const void *data, s
5050
size_t min_size = sizeof(*header);
5151
int i;
5252

53-
if (!huc_fw->loaded_via_gsc) {
53+
if (!huc_fw->has_gsc_headers) {
5454
huc_err(huc, "Invalid FW type for GSC header parsing!\n");
5555
return -EINVAL;
5656
}

drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ struct __packed uc_fw_blob {
186186
u8 major;
187187
u8 minor;
188188
u8 patch;
189-
bool loaded_via_gsc;
189+
bool has_gsc_headers;
190190
};
191191

192192
#define UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \
@@ -197,7 +197,7 @@ struct __packed uc_fw_blob {
197197

198198
#define UC_FW_BLOB_NEW(major_, minor_, patch_, gsc_, path_) \
199199
{ UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \
200-
.legacy = false, .loaded_via_gsc = gsc_ }
200+
.legacy = false, .has_gsc_headers = gsc_ }
201201

202202
#define UC_FW_BLOB_OLD(major_, minor_, patch_, path_) \
203203
{ UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \
@@ -310,7 +310,7 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
310310
uc_fw->file_wanted.ver.major = blob->major;
311311
uc_fw->file_wanted.ver.minor = blob->minor;
312312
uc_fw->file_wanted.ver.patch = blob->patch;
313-
uc_fw->loaded_via_gsc = blob->loaded_via_gsc;
313+
uc_fw->has_gsc_headers = blob->has_gsc_headers;
314314
found = true;
315315
break;
316316
}
@@ -737,7 +737,7 @@ static int check_fw_header(struct intel_gt *gt,
737737
if (uc_fw->type == INTEL_UC_FW_TYPE_GSC)
738738
return 0;
739739

740-
if (uc_fw->loaded_via_gsc)
740+
if (uc_fw->has_gsc_headers)
741741
err = check_gsc_manifest(gt, fw, uc_fw);
742742
else
743743
err = check_ccs_header(gt, fw, uc_fw);
@@ -999,7 +999,7 @@ static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
999999
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
10001000

10011001
/* Set the source address for the uCode */
1002-
offset = uc_fw->vma_res.start;
1002+
offset = uc_fw->vma_res.start + uc_fw->dma_start_offset;
10031003
GEM_BUG_ON(upper_32_bits(offset) & 0xFFFF0000);
10041004
intel_uncore_write_fw(uncore, DMA_ADDR_0_LOW, lower_32_bits(offset));
10051005
intel_uncore_write_fw(uncore, DMA_ADDR_0_HIGH, upper_32_bits(offset));
@@ -1238,7 +1238,7 @@ size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len)
12381238
{
12391239
struct intel_memory_region *mr = uc_fw->obj->mm.region;
12401240
u32 size = min_t(u32, uc_fw->rsa_size, max_len);
1241-
u32 offset = sizeof(struct uc_css_header) + uc_fw->ucode_size;
1241+
u32 offset = uc_fw->dma_start_offset + sizeof(struct uc_css_header) + uc_fw->ucode_size;
12421242
struct sgt_iter iter;
12431243
size_t count = 0;
12441244
int idx;

drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ struct intel_uc_fw {
120120

121121
u32 dma_start_offset;
122122

123-
bool loaded_via_gsc;
123+
bool has_gsc_headers;
124124
};
125125

126126
/*

0 commit comments

Comments
 (0)