Skip to content

Commit c31a0b6

Browse files
committed
drm/xe: Set LRC addresses before guc load
The metadata saved in the ADS is read by GuC when it's initialized. Saving the addresses to the LRCs when they are populated is too late as GuC will keep using the old ones. This was causing GuC to use the RCS LRC for any engine class. It's not a big problem on a Linux-only scenario since the they are used by GuC only on media engines when the watchdog is triggered. However, in a virtualization scenario with Windows as the VF, it causes the wrong LRCs to be loaded as the watchdog is used for all engines. Fix it by letting guc_golden_lrc_init() initialize the metadata, like other *_init() functions, and later guc_golden_lrc_populate() to copy the LRCs to the right places. The former is called before the second GuC load, while the latter is called after LRCs have been recorded. Cc: Chee Yin Wong <chee.yin.wong@intel.com> Cc: John Harrison <john.c.harrison@intel.com> Cc: Matt Roper <matthew.d.roper@intel.com> Cc: Matthew Brost <matthew.brost@intel.com> Fixes: dd08ebf ("drm/xe: Introduce a new DRM driver for Intel GPUs") Cc: <stable@vger.kernel.org> # v6.11+ Reviewed-by: Matthew Brost <matthew.brost@intel.com> Tested-by: Chee Yin Wong <chee.yin.wong@intel.com> Link: https://lore.kernel.org/r/20250409-fix-guc-ads-v1-1-494135f7a5d0@intel.com Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
1 parent 84d3763 commit c31a0b6

File tree

1 file changed

+45
-30
lines changed

1 file changed

+45
-30
lines changed

drivers/gpu/drm/xe/xe_guc_ads.c

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -496,24 +496,52 @@ static void fill_engine_enable_masks(struct xe_gt *gt,
496496
engine_enable_mask(gt, XE_ENGINE_CLASS_OTHER));
497497
}
498498

499-
static void guc_prep_golden_lrc_null(struct xe_guc_ads *ads)
499+
/*
500+
* Write the offsets corresponding to the golden LRCs. The actual data is
501+
* populated later by guc_golden_lrc_populate()
502+
*/
503+
static void guc_golden_lrc_init(struct xe_guc_ads *ads)
500504
{
501505
struct xe_device *xe = ads_to_xe(ads);
506+
struct xe_gt *gt = ads_to_gt(ads);
502507
struct iosys_map info_map = IOSYS_MAP_INIT_OFFSET(ads_to_map(ads),
503508
offsetof(struct __guc_ads_blob, system_info));
504-
u8 guc_class;
509+
size_t alloc_size, real_size;
510+
u32 addr_ggtt, offset;
511+
int class;
512+
513+
offset = guc_ads_golden_lrc_offset(ads);
514+
addr_ggtt = xe_bo_ggtt_addr(ads->bo) + offset;
515+
516+
for (class = 0; class < XE_ENGINE_CLASS_MAX; ++class) {
517+
u8 guc_class;
518+
519+
guc_class = xe_engine_class_to_guc_class(class);
505520

506-
for (guc_class = 0; guc_class <= GUC_MAX_ENGINE_CLASSES; ++guc_class) {
507521
if (!info_map_read(xe, &info_map,
508522
engine_enabled_masks[guc_class]))
509523
continue;
510524

525+
real_size = xe_gt_lrc_size(gt, class);
526+
alloc_size = PAGE_ALIGN(real_size);
527+
528+
/*
529+
* This interface is slightly confusing. We need to pass the
530+
* base address of the full golden context and the size of just
531+
* the engine state, which is the section of the context image
532+
* that starts after the execlists LRC registers. This is
533+
* required to allow the GuC to restore just the engine state
534+
* when a watchdog reset occurs.
535+
* We calculate the engine state size by removing the size of
536+
* what comes before it in the context image (which is identical
537+
* on all engines).
538+
*/
511539
ads_blob_write(ads, ads.eng_state_size[guc_class],
512-
guc_ads_golden_lrc_size(ads) -
513-
xe_lrc_skip_size(xe));
540+
real_size - xe_lrc_skip_size(xe));
514541
ads_blob_write(ads, ads.golden_context_lrca[guc_class],
515-
xe_bo_ggtt_addr(ads->bo) +
516-
guc_ads_golden_lrc_offset(ads));
542+
addr_ggtt);
543+
544+
addr_ggtt += alloc_size;
517545
}
518546
}
519547

@@ -863,7 +891,7 @@ void xe_guc_ads_populate_minimal(struct xe_guc_ads *ads)
863891

864892
xe_map_memset(ads_to_xe(ads), ads_to_map(ads), 0, 0, ads->bo->size);
865893
guc_policies_init(ads);
866-
guc_prep_golden_lrc_null(ads);
894+
guc_golden_lrc_init(ads);
867895
guc_mapping_table_init_invalid(gt, &info_map);
868896
guc_doorbell_init(ads);
869897

@@ -889,7 +917,7 @@ void xe_guc_ads_populate(struct xe_guc_ads *ads)
889917
guc_policies_init(ads);
890918
fill_engine_enable_masks(gt, &info_map);
891919
guc_mmio_reg_state_init(ads);
892-
guc_prep_golden_lrc_null(ads);
920+
guc_golden_lrc_init(ads);
893921
guc_mapping_table_init(gt, &info_map);
894922
guc_capture_prep_lists(ads);
895923
guc_doorbell_init(ads);
@@ -909,18 +937,22 @@ void xe_guc_ads_populate(struct xe_guc_ads *ads)
909937
guc_ads_private_data_offset(ads));
910938
}
911939

912-
static void guc_populate_golden_lrc(struct xe_guc_ads *ads)
940+
/*
941+
* After the golden LRC's are recorded for each engine class by the first
942+
* submission, copy them to the ADS, as initialized earlier by
943+
* guc_golden_lrc_init().
944+
*/
945+
static void guc_golden_lrc_populate(struct xe_guc_ads *ads)
913946
{
914947
struct xe_device *xe = ads_to_xe(ads);
915948
struct xe_gt *gt = ads_to_gt(ads);
916949
struct iosys_map info_map = IOSYS_MAP_INIT_OFFSET(ads_to_map(ads),
917950
offsetof(struct __guc_ads_blob, system_info));
918951
size_t total_size = 0, alloc_size, real_size;
919-
u32 addr_ggtt, offset;
952+
u32 offset;
920953
int class;
921954

922955
offset = guc_ads_golden_lrc_offset(ads);
923-
addr_ggtt = xe_bo_ggtt_addr(ads->bo) + offset;
924956

925957
for (class = 0; class < XE_ENGINE_CLASS_MAX; ++class) {
926958
u8 guc_class;
@@ -937,26 +969,9 @@ static void guc_populate_golden_lrc(struct xe_guc_ads *ads)
937969
alloc_size = PAGE_ALIGN(real_size);
938970
total_size += alloc_size;
939971

940-
/*
941-
* This interface is slightly confusing. We need to pass the
942-
* base address of the full golden context and the size of just
943-
* the engine state, which is the section of the context image
944-
* that starts after the execlists LRC registers. This is
945-
* required to allow the GuC to restore just the engine state
946-
* when a watchdog reset occurs.
947-
* We calculate the engine state size by removing the size of
948-
* what comes before it in the context image (which is identical
949-
* on all engines).
950-
*/
951-
ads_blob_write(ads, ads.eng_state_size[guc_class],
952-
real_size - xe_lrc_skip_size(xe));
953-
ads_blob_write(ads, ads.golden_context_lrca[guc_class],
954-
addr_ggtt);
955-
956972
xe_map_memcpy_to(xe, ads_to_map(ads), offset,
957973
gt->default_lrc[class], real_size);
958974

959-
addr_ggtt += alloc_size;
960975
offset += alloc_size;
961976
}
962977

@@ -965,7 +980,7 @@ static void guc_populate_golden_lrc(struct xe_guc_ads *ads)
965980

966981
void xe_guc_ads_populate_post_load(struct xe_guc_ads *ads)
967982
{
968-
guc_populate_golden_lrc(ads);
983+
guc_golden_lrc_populate(ads);
969984
}
970985

971986
static int guc_ads_action_update_policies(struct xe_guc_ads *ads, u32 policy_offset)

0 commit comments

Comments
 (0)