Skip to content

Commit 3532e75

Browse files
committed
drm/i915/uc: perma-pin firmwares
Now that each FW has its own reserved area, we can keep them always pinned and skip the pin/unpin dance on reset. This will make things easier for the 2-step HuC authentication, which requires the FW to be pinned in GGTT after the xfer is completed. Since the vma is now valid for a long time and not just for the quick pin-load-unpin dance, the name "dummy" is no longer appropriare and has been replaced with vma_res. All the functions have also been updated to operate on vma_res for consistency. Given that we pin the vma behind the allocator's back (which is ok because we do the pinning in an area that was previously reserved for thus purpose), we do need to explicitly re-pin on resume because the automated helper won't cover us. v2: better comments and commit message, s/dummy/vma_res/ 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-2-daniele.ceraolospurio@intel.com
1 parent 9ff17e6 commit 3532e75

8 files changed

Lines changed: 71 additions & 25 deletions

File tree

drivers/gpu/drm/i915/gt/intel_ggtt.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,9 @@ void i915_ggtt_resume(struct i915_ggtt *ggtt)
13261326
ggtt->vm.scratch_range(&ggtt->vm, ggtt->error_capture.start,
13271327
ggtt->error_capture.size);
13281328

1329+
list_for_each_entry(gt, &ggtt->gt_list, ggtt_link)
1330+
intel_uc_resume_mappings(&gt->uc);
1331+
13291332
ggtt->invalidate(ggtt);
13301333

13311334
if (flush)

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,12 @@ void intel_gsc_uc_init_early(struct intel_gsc_uc *gsc)
9090
{
9191
struct intel_gt *gt = gsc_uc_to_gt(gsc);
9292

93-
intel_uc_fw_init_early(&gsc->fw, INTEL_UC_FW_TYPE_GSC);
93+
/*
94+
* GSC FW needs to be copied to a dedicated memory allocations for
95+
* loading (see gsc->local), so we don't need to GGTT map the FW image
96+
* itself into GGTT.
97+
*/
98+
intel_uc_fw_init_early(&gsc->fw, INTEL_UC_FW_TYPE_GSC, false);
9499
INIT_WORK(&gsc->work, gsc_work);
95100

96101
/* we can arrive here from i915_driver_early_probe for primary

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ void intel_guc_init_early(struct intel_guc *guc)
163163
struct intel_gt *gt = guc_to_gt(guc);
164164
struct drm_i915_private *i915 = gt->i915;
165165

166-
intel_uc_fw_init_early(&guc->fw, INTEL_UC_FW_TYPE_GUC);
166+
intel_uc_fw_init_early(&guc->fw, INTEL_UC_FW_TYPE_GUC, true);
167167
intel_guc_ct_init_early(&guc->ct);
168168
intel_guc_log_init_early(&guc->log);
169169
intel_guc_submission_init_early(guc);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ void intel_huc_init_early(struct intel_huc *huc)
276276
struct drm_i915_private *i915 = huc_to_gt(huc)->i915;
277277
struct intel_gt *gt = huc_to_gt(huc);
278278

279-
intel_uc_fw_init_early(&huc->fw, INTEL_UC_FW_TYPE_HUC);
279+
intel_uc_fw_init_early(&huc->fw, INTEL_UC_FW_TYPE_HUC, true);
280280

281281
/*
282282
* we always init the fence as already completed, even if HuC is not

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,12 @@ void intel_uc_suspend(struct intel_uc *uc)
700700
}
701701
}
702702

703+
static void __uc_resume_mappings(struct intel_uc *uc)
704+
{
705+
intel_uc_fw_resume_mapping(&uc->guc.fw);
706+
intel_uc_fw_resume_mapping(&uc->huc.fw);
707+
}
708+
703709
static int __uc_resume(struct intel_uc *uc, bool enable_communication)
704710
{
705711
struct intel_guc *guc = &uc->guc;
@@ -767,4 +773,6 @@ static const struct intel_uc_ops uc_ops_on = {
767773

768774
.init_hw = __uc_init_hw,
769775
.fini_hw = __uc_fini_hw,
776+
777+
.resume_mappings = __uc_resume_mappings,
770778
};

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct intel_uc_ops {
2424
void (*fini)(struct intel_uc *uc);
2525
int (*init_hw)(struct intel_uc *uc);
2626
void (*fini_hw)(struct intel_uc *uc);
27+
void (*resume_mappings)(struct intel_uc *uc);
2728
};
2829

2930
struct intel_uc {
@@ -114,6 +115,7 @@ intel_uc_ops_function(init, init, int, 0);
114115
intel_uc_ops_function(fini, fini, void, );
115116
intel_uc_ops_function(init_hw, init_hw, int, 0);
116117
intel_uc_ops_function(fini_hw, fini_hw, void, );
118+
intel_uc_ops_function(resume_mappings, resume_mappings, void, );
117119
#undef intel_uc_ops_function
118120

119121
#endif

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

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -471,12 +471,14 @@ static void __uc_fw_user_override(struct drm_i915_private *i915, struct intel_uc
471471
* intel_uc_fw_init_early - initialize the uC object and select the firmware
472472
* @uc_fw: uC firmware
473473
* @type: type of uC
474+
* @needs_ggtt_mapping: whether the FW needs to be GGTT mapped for loading
474475
*
475476
* Initialize the state of our uC object and relevant tracking and select the
476477
* firmware to fetch and load.
477478
*/
478479
void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
479-
enum intel_uc_fw_type type)
480+
enum intel_uc_fw_type type,
481+
bool needs_ggtt_mapping)
480482
{
481483
struct intel_gt *gt = ____uc_fw_to_gt(uc_fw, type);
482484
struct drm_i915_private *i915 = gt->i915;
@@ -490,6 +492,7 @@ void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
490492
GEM_BUG_ON(uc_fw->file_selected.path);
491493

492494
uc_fw->type = type;
495+
uc_fw->needs_ggtt_mapping = needs_ggtt_mapping;
493496

494497
if (HAS_GT_UC(i915)) {
495498
if (!validate_fw_table_type(i915, type)) {
@@ -755,7 +758,7 @@ static int try_firmware_load(struct intel_uc_fw *uc_fw, const struct firmware **
755758
if (err)
756759
return err;
757760

758-
if ((*fw)->size > INTEL_UC_RSVD_GGTT_PER_FW) {
761+
if (uc_fw->needs_ggtt_mapping && (*fw)->size > INTEL_UC_RSVD_GGTT_PER_FW) {
759762
gt_err(gt, "%s firmware %s: size (%zuKB) exceeds max supported size (%uKB)\n",
760763
intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
761764
(*fw)->size / SZ_1K, INTEL_UC_RSVD_GGTT_PER_FW / SZ_1K);
@@ -940,41 +943,46 @@ static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw)
940943
{
941944
struct drm_i915_gem_object *obj = uc_fw->obj;
942945
struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
943-
struct i915_vma_resource *dummy = &uc_fw->dummy;
946+
struct i915_vma_resource *vma_res = &uc_fw->vma_res;
944947
u32 pte_flags = 0;
945948

946-
dummy->start = uc_fw_ggtt_offset(uc_fw);
947-
dummy->node_size = obj->base.size;
948-
dummy->bi.pages = obj->mm.pages;
949+
if (!uc_fw->needs_ggtt_mapping)
950+
return;
951+
952+
vma_res->start = uc_fw_ggtt_offset(uc_fw);
953+
vma_res->node_size = obj->base.size;
954+
vma_res->bi.pages = obj->mm.pages;
949955

950956
GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
951957

952958
/* uc_fw->obj cache domains were not controlled across suspend */
953959
if (i915_gem_object_has_struct_page(obj))
954-
drm_clflush_sg(dummy->bi.pages);
960+
drm_clflush_sg(vma_res->bi.pages);
955961

956962
if (i915_gem_object_is_lmem(obj))
957963
pte_flags |= PTE_LM;
958964

959965
if (ggtt->vm.raw_insert_entries)
960-
ggtt->vm.raw_insert_entries(&ggtt->vm, dummy,
966+
ggtt->vm.raw_insert_entries(&ggtt->vm, vma_res,
961967
i915_gem_get_pat_index(ggtt->vm.i915,
962968
I915_CACHE_NONE),
963969
pte_flags);
964970
else
965-
ggtt->vm.insert_entries(&ggtt->vm, dummy,
971+
ggtt->vm.insert_entries(&ggtt->vm, vma_res,
966972
i915_gem_get_pat_index(ggtt->vm.i915,
967973
I915_CACHE_NONE),
968974
pte_flags);
969975
}
970976

971977
static void uc_fw_unbind_ggtt(struct intel_uc_fw *uc_fw)
972978
{
973-
struct drm_i915_gem_object *obj = uc_fw->obj;
974979
struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
975-
u64 start = uc_fw_ggtt_offset(uc_fw);
980+
struct i915_vma_resource *vma_res = &uc_fw->vma_res;
981+
982+
if (!vma_res->node_size)
983+
return;
976984

977-
ggtt->vm.clear_range(&ggtt->vm, start, obj->base.size);
985+
ggtt->vm.clear_range(&ggtt->vm, vma_res->start, vma_res->node_size);
978986
}
979987

980988
static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
@@ -991,7 +999,7 @@ static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
991999
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
9921000

9931001
/* Set the source address for the uCode */
994-
offset = uc_fw_ggtt_offset(uc_fw);
1002+
offset = uc_fw->vma_res.start;
9951003
GEM_BUG_ON(upper_32_bits(offset) & 0xFFFF0000);
9961004
intel_uncore_write_fw(uncore, DMA_ADDR_0_LOW, lower_32_bits(offset));
9971005
intel_uncore_write_fw(uncore, DMA_ADDR_0_HIGH, upper_32_bits(offset));
@@ -1065,9 +1073,7 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
10651073
return -ENOEXEC;
10661074

10671075
/* Call custom loader */
1068-
uc_fw_bind_ggtt(uc_fw);
10691076
err = uc_fw_xfer(uc_fw, dst_offset, dma_flags);
1070-
uc_fw_unbind_ggtt(uc_fw);
10711077
if (err)
10721078
goto fail;
10731079

@@ -1171,6 +1177,8 @@ int intel_uc_fw_init(struct intel_uc_fw *uc_fw)
11711177
goto out_unpin;
11721178
}
11731179

1180+
uc_fw_bind_ggtt(uc_fw);
1181+
11741182
return 0;
11751183

11761184
out_unpin:
@@ -1181,6 +1189,7 @@ int intel_uc_fw_init(struct intel_uc_fw *uc_fw)
11811189

11821190
void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
11831191
{
1192+
uc_fw_unbind_ggtt(uc_fw);
11841193
uc_fw_rsa_data_destroy(uc_fw);
11851194

11861195
if (i915_gem_object_has_pinned_pages(uc_fw->obj))
@@ -1189,6 +1198,17 @@ void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
11891198
intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE);
11901199
}
11911200

1201+
void intel_uc_fw_resume_mapping(struct intel_uc_fw *uc_fw)
1202+
{
1203+
if (!intel_uc_fw_is_available(uc_fw))
1204+
return;
1205+
1206+
if (!i915_gem_object_has_pinned_pages(uc_fw->obj))
1207+
return;
1208+
1209+
uc_fw_bind_ggtt(uc_fw);
1210+
}
1211+
11921212
/**
11931213
* intel_uc_fw_cleanup_fetch - cleanup uC firmware
11941214
* @uc_fw: uC firmware

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,19 @@ struct intel_uc_fw {
9999
struct drm_i915_gem_object *obj;
100100

101101
/**
102-
* @dummy: A vma used in binding the uc fw to ggtt. We can't define this
103-
* vma on the stack as it can lead to a stack overflow, so we define it
104-
* here. Safe to have 1 copy per uc fw because the binding is single
105-
* threaded as it done during driver load (inherently single threaded)
106-
* or during a GT reset (mutex guarantees single threaded).
102+
* @needs_ggtt_mapping: indicates whether the fw object needs to be
103+
* pinned to ggtt. If true, the fw is pinned at init time and unpinned
104+
* during driver unload.
107105
*/
108-
struct i915_vma_resource dummy;
106+
bool needs_ggtt_mapping;
107+
108+
/**
109+
* @vma_res: A vma resource used in binding the uc fw to ggtt. The fw is
110+
* pinned in a reserved area of the ggtt (above the maximum address
111+
* usable by GuC); therefore, we can't use the normal vma functions to
112+
* do the pinning and we instead use this resource to do so.
113+
*/
114+
struct i915_vma_resource vma_res;
109115
struct i915_vma *rsa_data;
110116

111117
u32 rsa_size;
@@ -282,12 +288,14 @@ static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw)
282288
}
283289

284290
void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
285-
enum intel_uc_fw_type type);
291+
enum intel_uc_fw_type type,
292+
bool needs_ggtt_mapping);
286293
int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw);
287294
void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw);
288295
int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 offset, u32 dma_flags);
289296
int intel_uc_fw_init(struct intel_uc_fw *uc_fw);
290297
void intel_uc_fw_fini(struct intel_uc_fw *uc_fw);
298+
void intel_uc_fw_resume_mapping(struct intel_uc_fw *uc_fw);
291299
size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len);
292300
int intel_uc_fw_mark_load_failed(struct intel_uc_fw *uc_fw, int err);
293301
void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p);

0 commit comments

Comments
 (0)