[PATCH v2] drm/i915/guc: Enable w/a 16021333562 for DG2, MTL and ARL
From: John Harrison Enable another workaround that is implemented inside the GuC. v2: Use the correct Gen12 w/a id rather than the Xe version (review feedback from Matthew R) also extend to include ARL. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 32 --- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h index 525587cfe1af9..37ff539a6963d 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h @@ -106,6 +106,7 @@ enum { */ enum { GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE = 0x9001, + GUC_WORKAROUND_KLV_BLOCK_INTERRUPTS_WHEN_MGSR_BLOCKED = 0x9002, }; #endif /* _ABI_GUC_KLVS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index c606bb5e3b7b0..7995f059f30df 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -815,23 +815,23 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } -/* Wa_14019159160 */ -static u32 guc_waklv_ra_mode(struct intel_guc *guc, u32 offset, u32 remain) +static void guc_waklv_enable_simple(struct intel_guc *guc, + u32 klv_id, u32 *offset, u32 *remain) { u32 size; u32 klv_entry[] = { /* 16:16 key/length */ - FIELD_PREP(GUC_KLV_0_KEY, GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE) | + FIELD_PREP(GUC_KLV_0_KEY, klv_id) | FIELD_PREP(GUC_KLV_0_LEN, 0), /* 0 dwords data */ }; size = sizeof(klv_entry); - GEM_BUG_ON(remain < size); + GEM_BUG_ON(*remain < size); - iosys_map_memcpy_to(>ads_map, offset, klv_entry, size); - - return size; + iosys_map_memcpy_to(>ads_map, *offset, klv_entry, size); + *offset += size; + *remain -= size; } static void guc_waklv_init(struct intel_guc *guc) @@ -850,11 +850,19 @@ static void guc_waklv_init(struct intel_guc *guc) remain = guc_ads_waklv_size(guc); /* Wa_14019159160 */ - if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { - size = guc_waklv_ra_mode(guc, offset, remain); - offset += size; - remain -= size; - } + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) + guc_waklv_enable_simple(guc, + GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE, + , ); + + /* Wa_16021333562 */ + if ((GUC_FIRMWARE_VER(guc) >= MAKE_GUC_VER(70, 21, 1)) && + (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74)) || +IS_MEDIA_GT_IP_RANGE(gt, IP_VER(13, 0), IP_VER(13, 0)) || +IS_DG2(gt->i915))) + guc_waklv_enable_simple(guc, + GUC_WORKAROUND_KLV_BLOCK_INTERRUPTS_WHEN_MGSR_BLOCKED, + , ); size = guc_ads_waklv_size(guc) - remain; if (!size) -- 2.43.2
[PATCH] drm/i915/guc: Enable w/a 14019882105 for DG2 and MTL
From: John Harrison Enable another workaround that is implemented inside the GuC. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 32 --- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h index 525587cfe1af9..37ff539a6963d 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h @@ -106,6 +106,7 @@ enum { */ enum { GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE = 0x9001, + GUC_WORKAROUND_KLV_BLOCK_INTERRUPTS_WHEN_MGSR_BLOCKED = 0x9002, }; #endif /* _ABI_GUC_KLVS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index c606bb5e3b7b0..6c382785bc60b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -815,23 +815,23 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } -/* Wa_14019159160 */ -static u32 guc_waklv_ra_mode(struct intel_guc *guc, u32 offset, u32 remain) +static void guc_waklv_enable_simple(struct intel_guc *guc, + u32 klv_id, u32 *offset, u32 *remain) { u32 size; u32 klv_entry[] = { /* 16:16 key/length */ - FIELD_PREP(GUC_KLV_0_KEY, GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE) | + FIELD_PREP(GUC_KLV_0_KEY, klv_id) | FIELD_PREP(GUC_KLV_0_LEN, 0), /* 0 dwords data */ }; size = sizeof(klv_entry); - GEM_BUG_ON(remain < size); + GEM_BUG_ON(*remain < size); - iosys_map_memcpy_to(>ads_map, offset, klv_entry, size); - - return size; + iosys_map_memcpy_to(>ads_map, *offset, klv_entry, size); + *offset += size; + *remain -= size; } static void guc_waklv_init(struct intel_guc *guc) @@ -850,11 +850,19 @@ static void guc_waklv_init(struct intel_guc *guc) remain = guc_ads_waklv_size(guc); /* Wa_14019159160 */ - if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { - size = guc_waklv_ra_mode(guc, offset, remain); - offset += size; - remain -= size; - } + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) + guc_waklv_enable_simple(guc, + GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE, + , ); + + /* Wa_14019882105 */ + if ((GUC_FIRMWARE_VER(guc) >= MAKE_GUC_VER(70, 21, 1)) && + (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)) || +IS_MEDIA_GT_IP_RANGE(gt, IP_VER(13, 0), IP_VER(13, 0)) || +IS_DG2(gt->i915))) + guc_waklv_enable_simple(guc, + GUC_WORKAROUND_KLV_BLOCK_INTERRUPTS_WHEN_MGSR_BLOCKED, + , ); size = guc_ads_waklv_size(guc) - remain; if (!size) -- 2.43.2
[PATCH] drm/i915/guc: Fix the fix for reset lock confusion
From: John Harrison The previous fix for the circlular lock splat about the busyness worker wasn't quite complete. Even though the reset-in-progress flag is cleared at the start of intel_uc_reset_finish, the entire function is still inside the reset mutex lock. Not sure why the patch appeared to fix the issue both locally and in CI. However, it is now back again. There is a further complication the wedge code path within intel_gt_reset() jumps around so much it results in nested reset_prepare/_finish calls. That is, the call sequence is: intel_gt_reset | reset_prepare | __intel_gt_set_wedged | | reset_prepare | | reset_finish | reset_finish The nested finish means that even if the clear of the in-progress flag was moved to the end of _finish, it would still be clear for the entire second call. Surprisingly, this does not seem to be causing any other problems at present. As an aside, a wedge on fini does not call the finish functions at all. The reset_in_progress flag is left set (twice). So instead of trying to cancel the worker anywhere at all in the reset path, just add a cancel to intel_guc_submission_fini instead. Note that it is not a problem if the worker is still active during a reset. Either it will run before the reset path starts locking things and will simply block the reset code for a tiny amount of time. Or it will run after the locks have been acquired and will early exit due to the try-lock. Also, do not use the reset-in-progress flag to decide whether a synchronous cancel is safe (from a lockdep perspective) or not. Instead, use the actual reset mutex state (both the genuine one and the custom rolled BACKOFF one). Fixes: 0e00a8814eec ("drm/i915/guc: Avoid circular locking issue on busyness flush") Signed-off-by: John Harrison Cc: Zhanjun Dong Cc: John Harrison Cc: Andi Shyti Cc: Daniel Vetter Cc: Daniel Vetter Cc: Rodrigo Vivi Cc: Nirmoy Das Cc: Tvrtko Ursulin Cc: Umesh Nerlige Ramappa Cc: Andrzej Hajda Cc: Matt Roper Cc: Jonathan Cavitt Cc: Prathap Kumar Valsan Cc: Alan Previn Cc: Madhumitha Tolakanahalli Pradeep Cc: Daniele Ceraolo Spurio Cc: Ashutosh Dixit Cc: Dnyaneshwar Bhadane --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 23 --- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 4 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 16640d6dd0589..00757d6333e88 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1403,14 +1403,17 @@ static void guc_cancel_busyness_worker(struct intel_guc *guc) * Trying to pass a 'need_sync' or 'in_reset' flag all the way down through * every possible call stack is unfeasible. It would be too intrusive to many * areas that really don't care about the GuC backend. However, there is the -* 'reset_in_progress' flag available, so just use that. +* I915_RESET_BACKOFF flag and the gt->reset.mutex can be tested for is_locked. +* So just use those. Note that testing both is required due to the hideously +* complex nature of the i915 driver's reset code paths. * * And note that in the case of a reset occurring during driver unload -* (wedge_on_fini), skipping the cancel in _prepare (when the reset flag is set -* is fine because there is another cancel in _finish (when the reset flag is -* not). +* (wedged_on_fini), skipping the cancel in reset_prepare/reset_fini (when the +* reset flag/mutex are set) is fine because there is another explicit cancel in +* intel_guc_submission_fini (when the reset flag/mutex are not). */ - if (guc_to_gt(guc)->uc.reset_in_progress) + if (mutex_is_locked(_to_gt(guc)->reset.mutex) || + test_bit(I915_RESET_BACKOFF, _to_gt(guc)->reset.flags)) cancel_delayed_work(>timestamp.work); else cancel_delayed_work_sync(>timestamp.work); @@ -1424,8 +1427,6 @@ static void __reset_guc_busyness_stats(struct intel_guc *guc) unsigned long flags; ktime_t unused; - guc_cancel_busyness_worker(guc); - spin_lock_irqsave(>timestamp.lock, flags); guc_update_pm_timestamp(guc, ); @@ -2004,13 +2005,6 @@ void intel_guc_submission_cancel_requests(struct intel_guc *guc) void intel_guc_submission_reset_finish(struct intel_guc *guc) { - /* -* Ensure the busyness worker gets cancelled even on a fatal wedge. -* Note that reset_prepare is not allowed to because it confuses lockdep. -*/ - if (guc_submission_initialized(guc)) - guc_cancel_busyness_worker(guc); - /* Reset called during driver load or during wedge? */ if (unlikely(!guc_submission_initialized(guc) ||
[PATCH] drm/i915/guc: Update w/a 14019159160
From: John Harrison An existing workaround has been extended in both platforms affected and implementation complexity. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 3 ++- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 3 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 21 ++- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h index bebf28e3c4794..3e7060e859794 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h @@ -105,7 +105,8 @@ enum { * Workaround keys: */ enum { - GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE = 0x9001, + GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE = 0x9001, /* Wa_14019159160 */ + GUC_WORKAROUND_KLV_AVOID_GFX_CLEAR_WHILE_ACTIVE = 0x9006, /* Wa_14019159160 */ }; #endif /* _ABI_GUC_KLVS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 0c67d674c94de..4c3dae98656af 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -296,7 +296,8 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) /* Wa_16019325821 */ /* Wa_14019159160 */ - if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)) || + IS_DG2(gt->i915)) flags |= GUC_WA_RCS_CCS_SWITCHOUT; /* diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 5c9908b56616e..00fe3c21a9b1c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -815,23 +815,23 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } -/* Wa_14019159160 */ -static u32 guc_waklv_ra_mode(struct intel_guc *guc, u32 offset, u32 remain) +static void guc_waklv_enable_simple(struct intel_guc *guc, u32 *offset, u32 *remain, u32 klv_id) { u32 size; u32 klv_entry[] = { /* 16:16 key/length */ - FIELD_PREP(GUC_KLV_0_KEY, GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE) | + FIELD_PREP(GUC_KLV_0_KEY, klv_id) | FIELD_PREP(GUC_KLV_0_LEN, 0), /* 0 dwords data */ }; size = sizeof(klv_entry); - GEM_BUG_ON(remain < size); + GEM_BUG_ON(*remain < size); - iosys_map_memcpy_to(>ads_map, offset, klv_entry, size); + iosys_map_memcpy_to(>ads_map, *offset, klv_entry, size); - return size; + *offset += size; + *remain -= size; } static void guc_waklv_init(struct intel_guc *guc) @@ -850,10 +850,11 @@ static void guc_waklv_init(struct intel_guc *guc) remain = guc_ads_waklv_size(guc); /* Wa_14019159160 */ - if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { - size = guc_waklv_ra_mode(guc, offset, remain); - offset += size; - remain -= size; + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)) || IS_DG2(gt->i915)) { + guc_waklv_enable_simple(guc, , , + GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE); + guc_waklv_enable_simple(guc, , , + GUC_WORKAROUND_KLV_AVOID_GFX_CLEAR_WHILE_ACTIVE); } size = guc_ads_waklv_size(guc) - remain; -- 2.43.0
[PATCH v3 0/3] Enable Wa_14019159160 and Wa_16019325821 for MTL
From: John Harrison Enable Wa_14019159160 and Wa_16019325821 for MTL RCS/CCS workarounds for MTL. v2: Fix bug in WA KLV implementation (offset not being reset to start of list). Add better comment to prep patch about how KLVs can be added. Add a module parameter override and disable the w/a by default as it causes performance regressions and is only required by very specific workloads. v3: Rebase to latest tree. Drop module parameter as performance regression is apparently not detectable after all and a bunch of more common workloads have been seen to hit the issue. Signed-off-by: John Harrison John Harrison (3): drm/i915: Enable Wa_16019325821 drm/i915/guc: Add support for w/a KLVs drm/i915/guc: Enable Wa_14019159160 drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 22 +++-- drivers/gpu/drm/i915/gt/intel_engine_types.h | 8 +- .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 7 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.c| 5 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 89 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 8 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 8 +- 10 files changed, 141 insertions(+), 15 deletions(-) -- 2.43.0
[PATCH v3 2/3] drm/i915/guc: Add support for w/a KLVs
From: John Harrison To prevent running out of bits, new w/a enable flags are being added via a KLV system instead of a 32 bit flags word. Signed-off-by: John Harrison Reviewed-by: Vinay Belgaumkar --- .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 73 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 5 +- 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h index dabeaf4f245f3..00d6402333f8e 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h @@ -36,6 +36,7 @@ enum intel_guc_load_status { INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_START, INTEL_GUC_LOAD_STATUS_MPU_DATA_INVALID = 0x73, INTEL_GUC_LOAD_STATUS_INIT_MMIO_SAVE_RESTORE_INVALID = 0x74, + INTEL_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR= 0x75, INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_END, INTEL_GUC_LOAD_STATUS_READY= 0xF0, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index be70c46604b49..57b9031327767 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -204,6 +204,8 @@ struct intel_guc { struct guc_mmio_reg *ads_regset; /** @ads_golden_ctxt_size: size of the golden contexts in the ADS */ u32 ads_golden_ctxt_size; + /** @ads_waklv_size: size of workaround KLVs */ + u32 ads_waklv_size; /** @ads_capture_size: size of register lists in the ADS used for error capture */ u32 ads_capture_size; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index f7372f736a776..6af3fa8b92e34 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -46,6 +46,10 @@ * +---+ * | padding | * +---+ <== 4K aligned + * | w/a KLVs | + * +---+ + * | padding | + * +---+ <== 4K aligned * | capture lists | * +---+ * | padding | @@ -88,6 +92,11 @@ static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc) return PAGE_ALIGN(guc->ads_golden_ctxt_size); } +static u32 guc_ads_waklv_size(struct intel_guc *guc) +{ + return PAGE_ALIGN(guc->ads_waklv_size); +} + static u32 guc_ads_capture_size(struct intel_guc *guc) { return PAGE_ALIGN(guc->ads_capture_size); @@ -113,7 +122,7 @@ static u32 guc_ads_golden_ctxt_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } -static u32 guc_ads_capture_offset(struct intel_guc *guc) +static u32 guc_ads_waklv_offset(struct intel_guc *guc) { u32 offset; @@ -123,6 +132,16 @@ static u32 guc_ads_capture_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } +static u32 guc_ads_capture_offset(struct intel_guc *guc) +{ + u32 offset; + + offset = guc_ads_waklv_offset(guc) + +guc_ads_waklv_size(guc); + + return PAGE_ALIGN(offset); +} + static u32 guc_ads_private_data_offset(struct intel_guc *guc) { u32 offset; @@ -796,6 +815,49 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } +static void guc_waklv_init(struct intel_guc *guc) +{ + struct intel_gt *gt = guc_to_gt(guc); + u32 offset, addr_ggtt, remain, size; + + if (!intel_uc_uses_guc_submission(>uc)) + return; + + if (GUC_FIRMWARE_VER(guc) < MAKE_GUC_VER(70, 10, 0)) + return; + + GEM_BUG_ON(iosys_map_is_null(>ads_map)); + offset = guc_ads_waklv_offset(guc); + remain = guc_ads_waklv_size(guc); + + /* +* Add workarounds here: +* +* if (want_wa_) { +* size = guc_waklv_(guc, offset, remain); +* offset += size; +* remain -= size; +* } +*/ + + size = guc_ads_waklv_size(guc) - remain; + if (!size) + return; + + offset = guc_ads_waklv_offset(guc); + addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; + + ads_blob_write(guc, ads.wa_klv_addr_lo, addr_ggtt); + ads_blob_write(guc, ads.wa_klv_addr_hi, 0); + ads_blob_write(guc, ads.wa_klv_size, size); +} + +static int guc_prep_waklv(struct intel_guc *guc) +{ + /* Fudge something chunky for now: */ +
[PATCH v3 1/3] drm/i915: Enable Wa_16019325821
From: John Harrison Some platforms require holding RCS context switches until CCS is idle (the reverse w/a of Wa_14014475959). Some platforms require both versions. Signed-off-by: John Harrison Reviewed-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 19 +++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 7 --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 4 drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 3 ++- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 7 ++- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index e1bf13e3d3070..bb8e4c151a026 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -743,21 +743,23 @@ static u32 *gen12_emit_preempt_busywait(struct i915_request *rq, u32 *cs) } /* Wa_14014475959:dg2 */ -#define CCS_SEMAPHORE_PPHWSP_OFFSET0x540 -static u32 ccs_semaphore_offset(struct i915_request *rq) +/* Wa_16019325821 */ +#define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET 0x540 +static u32 hold_switchout_semaphore_offset(struct i915_request *rq) { return i915_ggtt_offset(rq->context->state) + - (LRC_PPHWSP_PN * PAGE_SIZE) + CCS_SEMAPHORE_PPHWSP_OFFSET; + (LRC_PPHWSP_PN * PAGE_SIZE) + HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET; } /* Wa_14014475959:dg2 */ -static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) +/* Wa_16019325821 */ +static u32 *hold_switchout_emit_wa_busywait(struct i915_request *rq, u32 *cs) { int i; *cs++ = MI_ATOMIC_INLINE | MI_ATOMIC_GLOBAL_GTT | MI_ATOMIC_CS_STALL | MI_ATOMIC_MOVE; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; *cs++ = 1; @@ -773,7 +775,7 @@ static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) MI_SEMAPHORE_POLL | MI_SEMAPHORE_SAD_EQ_SDD; *cs++ = 0; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; return cs; @@ -790,8 +792,9 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs) cs = gen12_emit_preempt_busywait(rq, cs); /* Wa_14014475959:dg2 */ - if (intel_engine_uses_wa_hold_ccs_switchout(rq->engine)) - cs = ccs_emit_wa_busywait(rq, cs); + /* Wa_16019325821 */ + if (intel_engine_uses_wa_hold_switchout(rq->engine)) + cs = hold_switchout_emit_wa_busywait(rq, cs); rq->tail = intel_ring_offset(rq, cs); assert_ring_tail_valid(rq->ring, rq->tail); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 960e6be2042fe..b519812ba120d 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -586,7 +586,7 @@ struct intel_engine_cs { #define I915_ENGINE_HAS_RCS_REG_STATE BIT(9) #define I915_ENGINE_HAS_EU_PRIORITYBIT(10) #define I915_ENGINE_FIRST_RENDER_COMPUTE BIT(11) -#define I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT BIT(12) +#define I915_ENGINE_USES_WA_HOLD_SWITCHOUT BIT(12) unsigned int flags; /* @@ -696,10 +696,11 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) } /* Wa_14014475959:dg2 */ +/* Wa_16019325821 */ static inline bool -intel_engine_uses_wa_hold_ccs_switchout(struct intel_engine_cs *engine) +intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine) { - return engine->flags & I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT; + return engine->flags & I915_ENGINE_USES_WA_HOLD_SWITCHOUT; } #endif /* __INTEL_ENGINE_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 2b450c43bbd7f..d5c856be31491 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -294,6 +294,10 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) IS_DG2(gt->i915)) flags |= GUC_WA_HOLD_CCS_SWITCHOUT; + /* Wa_16019325821 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) + flags |= GUC_WA_RCS_CCS_SWITCHOUT; + /* * Wa_14012197797 * Wa_22011391025 diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 8ae1846431da7..48863188a130e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -96,8 +96,9 @@ #define GUC_WA_GAM_CREDITS BIT(10) #define GUC_WA_DUAL_QUEUEBIT(11) #define GUC_WA_RCS_RESET_BEFORE_RC6 BIT(13) -#define GUC_WA_CONTEXT_ISOLATION BIT(15) #define GUC_WA_PRE_PARSERBIT(14) +#define GUC_WA_CONTEXT_ISOLATION BIT(15) +#define
[PATCH v3 3/3] drm/i915/guc: Enable Wa_14019159160
From: John Harrison Use the new w/a KLV support to enable a MTL w/a. Note, this w/a is a super-set of Wa_16019325821, so requires turning that one as well as setting the new flag for Wa_14019159160 itself. Signed-off-by: John Harrison Reviewed-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 3 ++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 1 + drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 7 drivers/gpu/drm/i915/gt/uc/intel_guc.c| 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 34 ++- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 1 + 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index bb8e4c151a026..8cf58b29410bc 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -744,6 +744,7 @@ static u32 *gen12_emit_preempt_busywait(struct i915_request *rq, u32 *cs) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ #define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET 0x540 static u32 hold_switchout_semaphore_offset(struct i915_request *rq) { @@ -753,6 +754,7 @@ static u32 hold_switchout_semaphore_offset(struct i915_request *rq) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ static u32 *hold_switchout_emit_wa_busywait(struct i915_request *rq, u32 *cs) { int i; @@ -793,6 +795,7 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ + /* Wa_14019159160 */ if (intel_engine_uses_wa_hold_switchout(rq->engine)) cs = hold_switchout_emit_wa_busywait(rq, cs); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index b519812ba120d..ba55c059063db 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -697,6 +697,7 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ static inline bool intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine) { diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h index 58012edd4eb0e..bebf28e3c4794 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h @@ -101,4 +101,11 @@ enum { GUC_CONTEXT_POLICIES_KLV_NUM_IDS = 5, }; +/* + * Workaround keys: + */ +enum { + GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE = 0x9001, +}; + #endif /* _ABI_GUC_KLVS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index d5c856be31491..db3cb628f40dc 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -295,6 +295,7 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) flags |= GUC_WA_HOLD_CCS_SWITCHOUT; /* Wa_16019325821 */ + /* Wa_14019159160 */ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) flags |= GUC_WA_RCS_CCS_SWITCHOUT; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 6af3fa8b92e34..68d9e277eca8b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -815,6 +815,25 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } +/* Wa_14019159160 */ +static u32 guc_waklv_ra_mode(struct intel_guc *guc, u32 offset, u32 remain) +{ + u32 size; + u32 klv_entry[] = { + /* 16:16 key/length */ + FIELD_PREP(GUC_KLV_0_KEY, GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE) | + FIELD_PREP(GUC_KLV_0_LEN, 0), + /* 0 dwords data */ + }; + + size = sizeof(klv_entry); + GEM_BUG_ON(remain < size); + + iosys_map_memcpy_to(>ads_map, offset, klv_entry, size); + + return size; +} + static void guc_waklv_init(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -830,15 +849,12 @@ static void guc_waklv_init(struct intel_guc *guc) offset = guc_ads_waklv_offset(guc); remain = guc_ads_waklv_size(guc); - /* -* Add workarounds here: -* -* if (want_wa_) { -* size = guc_waklv_(guc, offset, remain); -* offset += size; -* remain -= size; -* } -*/ + /* Wa_14019159160 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { + size = guc_waklv_ra_mode(guc, offset, remain); + offset += size; + remain -= size; + } size = guc_ads_waklv_size(guc) - remain; if (!size) diff --git
[PATCH] drm/i915/guc: Correct capture of EIR register on hang
From: John Harrison The EIR register (0x20B0) was being included in the engine class list for render and compute as the absolute register address. However, it is actually a ring register available on all engines at an offset of (base) + 0xB0. As it was included as an RCS engine but with the absolute address, GuC was adding on another 0x2000 and coming out at an invalid location. Thus it would reject the register and complain about only managing a partial capture. So update the list to use the RING_EIR version of the register and include it for all engines. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index a1cd40d805178..0cb5f22a173cb 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -51,6 +51,7 @@ { RING_ESR(0), 0, 0, "ESR" }, \ { RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LDW" }, \ { RING_DMA_FADD_UDW(0), 0, 0, "RING_DMA_FADD_UDW" }, \ + { RING_EIR(0), 0, 0, "EIR" }, \ { RING_IPEIR(0),0, 0, "IPEIR" }, \ { RING_IPEHR(0),0, 0, "IPEHR" }, \ { RING_INSTPS(0), 0, 0, "INSTPS" }, \ @@ -80,9 +81,6 @@ { GEN8_RING_PDP_LDW(0, 3), 0, 0, "PDP3_LDW" }, \ { GEN8_RING_PDP_UDW(0, 3), 0, 0, "PDP3_UDW" } -#define COMMON_BASE_HAS_EU \ - { EIR, 0, 0, "EIR" } - #define COMMON_BASE_RENDER \ { GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE" } @@ -105,7 +103,6 @@ static const struct __guc_mmio_reg_descr xe_lp_global_regs[] = { /* XE_LP Render / Compute Per-Class */ static const struct __guc_mmio_reg_descr xe_lp_rc_class_regs[] = { - COMMON_BASE_HAS_EU, COMMON_BASE_RENDER, COMMON_GEN12BASE_RENDER, }; @@ -148,7 +145,6 @@ static const struct __guc_mmio_reg_descr gen8_global_regs[] = { }; static const struct __guc_mmio_reg_descr gen8_rc_class_regs[] = { - COMMON_BASE_HAS_EU, COMMON_BASE_RENDER, }; -- 2.43.0
[PATCH v3] drm/i915/guc: Simplify/extend platform check for Wa_14018913170
From: John Harrison The above w/a is required for every platform that the i915 driver supports. It is fixed on the latest platforms but they are only supported by Xe instead of i915. So just remove the platform check completely and keep the code simple. v2: Add extra comment (review feedback from Rodrigo). Signed-off-by: John Harrison Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 2b450c43bbd7f..d2b7425bbdcc2 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -319,10 +319,12 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) if (!RCS_MASK(gt)) flags |= GUC_WA_RCS_REGS_IN_CCS_REGS_LIST; - /* Wa_14018913170 */ + /* +* Wa_14018913170: Applicable to all platforms supported by i915 so +* don't bother testing for all X/Y/Z platforms explicitly. +*/ if (GUC_FIRMWARE_VER(guc) >= MAKE_GUC_VER(70, 7, 0)) { - if (IS_DG2(gt->i915) || IS_METEORLAKE(gt->i915) || IS_PONTEVECCHIO(gt->i915)) - flags |= GUC_WA_ENABLE_TSC_CHECK_ON_RC6; + flags |= GUC_WA_ENABLE_TSC_CHECK_ON_RC6; } return flags; -- 2.43.0
PR for new GuC v70.20.0 binaries
The following changes since commit fbef4d381e3d0143427e1a8c924be8e738c0fc2d: Merge branch 'main' into 'main' (2024-02-08 12:24:01 +) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm-firmware guc_70.20.0 for you to fetch changes up to 28c2472d37d089edb56c75e3af83511babaa756c: xe: First GuC release for LNL and Xe (2024-02-14 16:28:32 -0800) John Harrison (2): i915: Add GuC v70.20.0 for ADL-P, DG1, DG2, MTL and TGL xe: First GuC release for LNL and Xe LICENSE.xe | 39 +++ WHENCE | 20 ++-- i915/adlp_guc_70.bin | Bin 342848 -> 347584 bytes i915/dg1_guc_70.bin | Bin 272512 -> 321472 bytes i915/dg2_guc_70.bin | Bin 443200 -> 410368 bytes i915/mtl_guc_70.bin | Bin 365376 -> 332544 bytes i915/tgl_guc_70.bin | Bin 330304 -> 335168 bytes xe/lnl_guc_70.bin| Bin 0 -> 336640 bytes 8 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 LICENSE.xe create mode 100644 xe/lnl_guc_70.bin
[PATCH v3] drm/i915/guc: Simplify/extend platform check for Wa_14018913170
From: John Harrison The above w/a is required for every platform that the i915 driver supports. It is fixed on the latest platforms but they are only supported by Xe instead of i915. So just remove the platform check completely and keep the code simple. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 2b450c43bbd7f..a3662edb42032 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -321,8 +321,7 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) /* Wa_14018913170 */ if (GUC_FIRMWARE_VER(guc) >= MAKE_GUC_VER(70, 7, 0)) { - if (IS_DG2(gt->i915) || IS_METEORLAKE(gt->i915) || IS_PONTEVECCHIO(gt->i915)) - flags |= GUC_WA_ENABLE_TSC_CHECK_ON_RC6; + flags |= GUC_WA_ENABLE_TSC_CHECK_ON_RC6; } return flags; -- 2.43.0
[CI] PR for new GuC v70.20.0
The following changes since commit fbef4d381e3d0143427e1a8c924be8e738c0fc2d: Merge branch 'main' into 'main' (2024-02-08 12:24:01 +) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm-firmware guc_70.20.0_with_pvc for you to fetch changes up to 609c1c4654f7f5f0c96f737679a823a29e44ca1e: xe: Add GuC 70.20.0 for PVC (2024-02-14 16:34:11 -0800) Daniele Ceraolo Spurio (1): xe: Add GuC 70.20.0 for PVC John Harrison (2): i915: Add GuC v70.20.0 for ADL-P, DG1, DG2, MTL and TGL xe: First GuC release for LNL and Xe LICENSE.xe | 39 +++ WHENCE | 23 +-- i915/adlp_guc_70.bin | Bin 342848 -> 347584 bytes i915/dg1_guc_70.bin| Bin 272512 -> 321472 bytes i915/dg2_guc_70.bin| Bin 443200 -> 410368 bytes i915/mtl_guc_70.bin| Bin 365376 -> 332544 bytes i915/tgl_guc_70.bin| Bin 330304 -> 335168 bytes xe/lnl_guc_70.bin | Bin 0 -> 336640 bytes xe/pvc_guc_70.20.0.bin | Bin 0 -> 553728 bytes 9 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 LICENSE.xe create mode 100644 xe/lnl_guc_70.bin create mode 100644 xe/pvc_guc_70.20.0.bin
PR for new GuC v70.19.2
The following changes since commit 1a9518c73c4b54854c9cd8f416fd3b8f8e3456e7: Merge branch 'mlimonci/amd-2024-01-30.2' into 'main' (2024-01-30 15:55:30 +) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm-firmware guc_70.19.2 for you to fetch changes up to 92c06b3c1b4b93ccd9953825cfd4e6ab56e03f16: xe: First GuC release for LNL and Xe (2024-01-30 09:23:50 -0800) John Harrison (2): i915: Add GuC v70.19.2 for ADL-P, DG1, DG2, MTL and TGL xe: First GuC release for LNL and Xe LICENSE.xe | 39 +++ WHENCE | 20 ++-- i915/adlp_guc_70.bin | Bin 342848 -> 347264 bytes i915/dg1_guc_70.bin | Bin 272512 -> 321088 bytes i915/dg2_guc_70.bin | Bin 443200 -> 406336 bytes i915/mtl_guc_70.bin | Bin 365376 -> 332608 bytes i915/tgl_guc_70.bin | Bin 330304 -> 334784 bytes xe/lnl_guc_70.bin| Bin 0 -> 336704 bytes 8 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 LICENSE.xe create mode 100644 xe/lnl_guc_70.bin
[CI] PR for new GuC v70.19.2
The following changes since commit 1a9518c73c4b54854c9cd8f416fd3b8f8e3456e7: Merge branch 'mlimonci/amd-2024-01-30.2' into 'main' (2024-01-30 15:55:30 +) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm-firmware guc_70.19.2 for you to fetch changes up to 92c06b3c1b4b93ccd9953825cfd4e6ab56e03f16: xe: First GuC release for LNL and Xe (2024-01-30 09:23:50 -0800) John Harrison (2): i915: Add GuC v70.19.2 for ADL-P, DG1, DG2, MTL and TGL xe: First GuC release for LNL and Xe LICENSE.xe | 39 +++ WHENCE | 20 ++-- i915/adlp_guc_70.bin | Bin 342848 -> 347264 bytes i915/dg1_guc_70.bin | Bin 272512 -> 321088 bytes i915/dg2_guc_70.bin | Bin 443200 -> 406336 bytes i915/mtl_guc_70.bin | Bin 365376 -> 332608 bytes i915/tgl_guc_70.bin | Bin 330304 -> 334784 bytes xe/lnl_guc_70.bin| Bin 0 -> 336704 bytes 8 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 LICENSE.xe create mode 100644 xe/lnl_guc_70.bin
[PATCH] drm/i915/gt: Restart the heartbeat timer when forcing a pulse
From: John Harrison The context persistence code does things like send super high priority heartbeat pulses to ensure any leaked context can still be pre-empted and thus isn't a total denial of service but only a minor denial of service. Unfortunately, it wasn't bothering to restart the heatbeat worker with a fresh timeout. Thus, if a persistent context happened to be closed just before the heartbeat was going to go ping anyway then the forced pulse would get a negligble execution time. And as the forced pulse is super high priority, the worker thread's next step is a reset. Which means a potentially innocent system randomly goes boom when attempting to close a context. So, force a re-schedule of the worker thread with the appropriate timeout. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c index 1a8e2b7db0138..4ae2fa0b61dd4 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c @@ -290,6 +290,9 @@ static int __intel_engine_pulse(struct intel_engine_cs *engine) heartbeat_commit(rq, ); GEM_BUG_ON(rq->sched.attr.priority < I915_PRIORITY_BARRIER); + /* Ensure the forced pulse gets a full period to execute */ + next_heartbeat(engine); + return 0; } -- 2.43.0
[PATCH v3 3/3] drm/i915/guc: Enable Wa_14019159160
From: John Harrison Use the new w/a KLV support to enable a MTL w/a. Note, this w/a is a super-set of Wa_16019325821, so requires turning that one as well as setting the new flag for Wa_14019159160 itself. Signed-off-by: John Harrison Reviewed-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 3 ++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 1 + drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 7 drivers/gpu/drm/i915/gt/uc/intel_guc.c| 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 34 ++- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 1 + 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index 9cccd60a5c41d..359b21fb02ab2 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -744,6 +744,7 @@ static u32 *gen12_emit_preempt_busywait(struct i915_request *rq, u32 *cs) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ #define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET 0x540 static u32 hold_switchout_semaphore_offset(struct i915_request *rq) { @@ -753,6 +754,7 @@ static u32 hold_switchout_semaphore_offset(struct i915_request *rq) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ static u32 *hold_switchout_emit_wa_busywait(struct i915_request *rq, u32 *cs) { int i; @@ -793,6 +795,7 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ + /* Wa_14019159160 */ if (intel_engine_uses_wa_hold_switchout(rq->engine)) cs = hold_switchout_emit_wa_busywait(rq, cs); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index b519812ba120d..ba55c059063db 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -697,6 +697,7 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ static inline bool intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine) { diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h index 58012edd4eb0e..bebf28e3c4794 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h @@ -101,4 +101,11 @@ enum { GUC_CONTEXT_POLICIES_KLV_NUM_IDS = 5, }; +/* + * Workaround keys: + */ +enum { + GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE = 0x9001, +}; + #endif /* _ABI_GUC_KLVS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index d5c856be31491..db3cb628f40dc 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -295,6 +295,7 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) flags |= GUC_WA_HOLD_CCS_SWITCHOUT; /* Wa_16019325821 */ + /* Wa_14019159160 */ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) flags |= GUC_WA_RCS_CCS_SWITCHOUT; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 6af3fa8b92e34..68d9e277eca8b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -815,6 +815,25 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } +/* Wa_14019159160 */ +static u32 guc_waklv_ra_mode(struct intel_guc *guc, u32 offset, u32 remain) +{ + u32 size; + u32 klv_entry[] = { + /* 16:16 key/length */ + FIELD_PREP(GUC_KLV_0_KEY, GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE) | + FIELD_PREP(GUC_KLV_0_LEN, 0), + /* 0 dwords data */ + }; + + size = sizeof(klv_entry); + GEM_BUG_ON(remain < size); + + iosys_map_memcpy_to(>ads_map, offset, klv_entry, size); + + return size; +} + static void guc_waklv_init(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -830,15 +849,12 @@ static void guc_waklv_init(struct intel_guc *guc) offset = guc_ads_waklv_offset(guc); remain = guc_ads_waklv_size(guc); - /* -* Add workarounds here: -* -* if (want_wa_) { -* size = guc_waklv_(guc, offset, remain); -* offset += size; -* remain -= size; -* } -*/ + /* Wa_14019159160 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { + size = guc_waklv_ra_mode(guc, offset, remain); + offset += size; + remain -= size; + } size = guc_ads_waklv_size(guc) - remain; if (!size) diff --git
[PATCH v3 2/3] drm/i915/guc: Add support for w/a KLVs
From: John Harrison To prevent running out of bits, new w/a enable flags are being added via a KLV system instead of a 32 bit flags word. Signed-off-by: John Harrison Reviewed-by: Vinay Belgaumkar --- .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 73 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 5 +- 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h index dabeaf4f245f3..00d6402333f8e 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h @@ -36,6 +36,7 @@ enum intel_guc_load_status { INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_START, INTEL_GUC_LOAD_STATUS_MPU_DATA_INVALID = 0x73, INTEL_GUC_LOAD_STATUS_INIT_MMIO_SAVE_RESTORE_INVALID = 0x74, + INTEL_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR= 0x75, INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_END, INTEL_GUC_LOAD_STATUS_READY= 0xF0, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 813cc888e6fae..b572fc10fd24d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -204,6 +204,8 @@ struct intel_guc { struct guc_mmio_reg *ads_regset; /** @ads_golden_ctxt_size: size of the golden contexts in the ADS */ u32 ads_golden_ctxt_size; + /** @ads_waklv_size: size of workaround KLVs */ + u32 ads_waklv_size; /** @ads_capture_size: size of register lists in the ADS used for error capture */ u32 ads_capture_size; /** @ads_engine_usage_size: size of engine usage in the ADS */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index f7372f736a776..6af3fa8b92e34 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -46,6 +46,10 @@ * +---+ * | padding | * +---+ <== 4K aligned + * | w/a KLVs | + * +---+ + * | padding | + * +---+ <== 4K aligned * | capture lists | * +---+ * | padding | @@ -88,6 +92,11 @@ static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc) return PAGE_ALIGN(guc->ads_golden_ctxt_size); } +static u32 guc_ads_waklv_size(struct intel_guc *guc) +{ + return PAGE_ALIGN(guc->ads_waklv_size); +} + static u32 guc_ads_capture_size(struct intel_guc *guc) { return PAGE_ALIGN(guc->ads_capture_size); @@ -113,7 +122,7 @@ static u32 guc_ads_golden_ctxt_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } -static u32 guc_ads_capture_offset(struct intel_guc *guc) +static u32 guc_ads_waklv_offset(struct intel_guc *guc) { u32 offset; @@ -123,6 +132,16 @@ static u32 guc_ads_capture_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } +static u32 guc_ads_capture_offset(struct intel_guc *guc) +{ + u32 offset; + + offset = guc_ads_waklv_offset(guc) + +guc_ads_waklv_size(guc); + + return PAGE_ALIGN(offset); +} + static u32 guc_ads_private_data_offset(struct intel_guc *guc) { u32 offset; @@ -796,6 +815,49 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } +static void guc_waklv_init(struct intel_guc *guc) +{ + struct intel_gt *gt = guc_to_gt(guc); + u32 offset, addr_ggtt, remain, size; + + if (!intel_uc_uses_guc_submission(>uc)) + return; + + if (GUC_FIRMWARE_VER(guc) < MAKE_GUC_VER(70, 10, 0)) + return; + + GEM_BUG_ON(iosys_map_is_null(>ads_map)); + offset = guc_ads_waklv_offset(guc); + remain = guc_ads_waklv_size(guc); + + /* +* Add workarounds here: +* +* if (want_wa_) { +* size = guc_waklv_(guc, offset, remain); +* offset += size; +* remain -= size; +* } +*/ + + size = guc_ads_waklv_size(guc) - remain; + if (!size) + return; + + offset = guc_ads_waklv_offset(guc); + addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; + + ads_blob_write(guc, ads.wa_klv_addr_lo, addr_ggtt); + ads_blob_write(guc, ads.wa_klv_addr_hi, 0); + ads_blob_write(guc, ads.wa_klv_size, size); +} + +static int guc_prep_waklv(struct intel_guc
[PATCH v3 0/3] Enable Wa_14019159160 and Wa_16019325821 for MTL
From: John Harrison Enable Wa_14019159160 and Wa_16019325821 for MTL RCS/CCS workarounds for MTL. v2: Fix bug in WA KLV implementation (offset not being reset to start of list). Add better comment to prep patch about how KLVs can be added. Add a module parameter override and disable the w/a by default as it causes performance regressions and is only required by very specific workloads. v3: Rebase to latest tree. Drop module parameter as performance regression is apparently not detectable after all and a bunch of more common workloads have been seen to hit the issue. Signed-off-by: John Harrison John Harrison (3): drm/i915: Enable Wa_16019325821 drm/i915/guc: Add support for w/a KLVs drm/i915/guc: Enable Wa_14019159160 drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 22 +++-- drivers/gpu/drm/i915/gt/intel_engine_types.h | 8 +- .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 7 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.c| 5 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 89 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 8 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 8 +- 10 files changed, 141 insertions(+), 15 deletions(-) -- 2.41.0
[PATCH v3 1/3] drm/i915: Enable Wa_16019325821
From: John Harrison Some platforms require holding RCS context switches until CCS is idle (the reverse w/a of Wa_14014475959). Some platforms require both versions. Signed-off-by: John Harrison Reviewed-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 19 +++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 7 --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 4 drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 3 ++- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 7 ++- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index 86a04afff64b3..9cccd60a5c41d 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -743,21 +743,23 @@ static u32 *gen12_emit_preempt_busywait(struct i915_request *rq, u32 *cs) } /* Wa_14014475959:dg2 */ -#define CCS_SEMAPHORE_PPHWSP_OFFSET0x540 -static u32 ccs_semaphore_offset(struct i915_request *rq) +/* Wa_16019325821 */ +#define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET 0x540 +static u32 hold_switchout_semaphore_offset(struct i915_request *rq) { return i915_ggtt_offset(rq->context->state) + - (LRC_PPHWSP_PN * PAGE_SIZE) + CCS_SEMAPHORE_PPHWSP_OFFSET; + (LRC_PPHWSP_PN * PAGE_SIZE) + HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET; } /* Wa_14014475959:dg2 */ -static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) +/* Wa_16019325821 */ +static u32 *hold_switchout_emit_wa_busywait(struct i915_request *rq, u32 *cs) { int i; *cs++ = MI_ATOMIC_INLINE | MI_ATOMIC_GLOBAL_GTT | MI_ATOMIC_CS_STALL | MI_ATOMIC_MOVE; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; *cs++ = 1; @@ -773,7 +775,7 @@ static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) MI_SEMAPHORE_POLL | MI_SEMAPHORE_SAD_EQ_SDD; *cs++ = 0; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; return cs; @@ -790,8 +792,9 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs) cs = gen12_emit_preempt_busywait(rq, cs); /* Wa_14014475959:dg2 */ - if (intel_engine_uses_wa_hold_ccs_switchout(rq->engine)) - cs = ccs_emit_wa_busywait(rq, cs); + /* Wa_16019325821 */ + if (intel_engine_uses_wa_hold_switchout(rq->engine)) + cs = hold_switchout_emit_wa_busywait(rq, cs); rq->tail = intel_ring_offset(rq, cs); assert_ring_tail_valid(rq->ring, rq->tail); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 960e6be2042fe..b519812ba120d 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -586,7 +586,7 @@ struct intel_engine_cs { #define I915_ENGINE_HAS_RCS_REG_STATE BIT(9) #define I915_ENGINE_HAS_EU_PRIORITYBIT(10) #define I915_ENGINE_FIRST_RENDER_COMPUTE BIT(11) -#define I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT BIT(12) +#define I915_ENGINE_USES_WA_HOLD_SWITCHOUT BIT(12) unsigned int flags; /* @@ -696,10 +696,11 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) } /* Wa_14014475959:dg2 */ +/* Wa_16019325821 */ static inline bool -intel_engine_uses_wa_hold_ccs_switchout(struct intel_engine_cs *engine) +intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine) { - return engine->flags & I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT; + return engine->flags & I915_ENGINE_USES_WA_HOLD_SWITCHOUT; } #endif /* __INTEL_ENGINE_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 2b450c43bbd7f..d5c856be31491 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -294,6 +294,10 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) IS_DG2(gt->i915)) flags |= GUC_WA_HOLD_CCS_SWITCHOUT; + /* Wa_16019325821 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) + flags |= GUC_WA_RCS_CCS_SWITCHOUT; + /* * Wa_14012197797 * Wa_22011391025 diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 8ae1846431da7..48863188a130e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -96,8 +96,9 @@ #define GUC_WA_GAM_CREDITS BIT(10) #define GUC_WA_DUAL_QUEUEBIT(11) #define GUC_WA_RCS_RESET_BEFORE_RC6 BIT(13) -#define GUC_WA_CONTEXT_ISOLATION BIT(15) #define GUC_WA_PRE_PARSERBIT(14) +#define GUC_WA_CONTEXT_ISOLATION BIT(15) +#define
[PATCH] drm/i915/huc: Allow for very slow HuC loading
From: John Harrison A failure to load the HuC is occasionally observed where the cause is believed to be a low GT frequency leading to very long load times. So a) increase the timeout so that the user still gets a working system even in the case of slow load. And b) report the frequency during the load to see if that is the cause of the slow down. Also update the similar code on the GuC load to not use uncore->gt when there is a local gt available. The two should match, but no need for unnecessary de-referencing. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 10 ++-- drivers/gpu/drm/i915/gt/uc/intel_huc.c| 64 --- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 0f79cb6585182..52332bb143395 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -184,7 +184,7 @@ static int guc_wait_ucode(struct intel_guc *guc) * in the seconds range. However, there is a limit on how long an * individual wait_for() can wait. So wrap it in a loop. */ - before_freq = intel_rps_read_actual_frequency(>gt->rps); + before_freq = intel_rps_read_actual_frequency(>rps); before = ktime_get(); for (count = 0; count < GUC_LOAD_RETRY_LIMIT; count++) { ret = wait_for(guc_load_done(uncore, , ), 1000); @@ -192,7 +192,7 @@ static int guc_wait_ucode(struct intel_guc *guc) break; guc_dbg(guc, "load still in progress, count = %d, freq = %dMHz, status = 0x%08X [0x%02X/%02X]\n", - count, intel_rps_read_actual_frequency(>gt->rps), status, + count, intel_rps_read_actual_frequency(>rps), status, REG_FIELD_GET(GS_BOOTROM_MASK, status), REG_FIELD_GET(GS_UKERNEL_MASK, status)); } @@ -204,7 +204,7 @@ static int guc_wait_ucode(struct intel_guc *guc) u32 bootrom = REG_FIELD_GET(GS_BOOTROM_MASK, status); guc_info(guc, "load failed: status = 0x%08X, time = %lldms, freq = %dMHz, ret = %d\n", -status, delta_ms, intel_rps_read_actual_frequency(>gt->rps), ret); +status, delta_ms, intel_rps_read_actual_frequency(>rps), ret); guc_info(guc, "load failed: status: Reset = %d, BootROM = 0x%02X, UKernel = 0x%02X, MIA = 0x%02X, Auth = 0x%02X\n", REG_FIELD_GET(GS_MIA_IN_RESET, status), bootrom, ukernel, @@ -254,11 +254,11 @@ static int guc_wait_ucode(struct intel_guc *guc) guc_warn(guc, "excessive init time: %lldms! [status = 0x%08X, count = %d, ret = %d]\n", delta_ms, status, count, ret); guc_warn(guc, "excessive init time: [freq = %dMHz, before = %dMHz, perf_limit_reasons = 0x%08X]\n", -intel_rps_read_actual_frequency(>gt->rps), before_freq, +intel_rps_read_actual_frequency(>rps), before_freq, intel_uncore_read(uncore, intel_gt_perf_limit_reasons_reg(gt))); } else { guc_dbg(guc, "init took %lldms, freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d\n", - delta_ms, intel_rps_read_actual_frequency(>gt->rps), + delta_ms, intel_rps_read_actual_frequency(>rps), before_freq, status, count, ret); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c index ba9e07fc2b577..9ccec7de9628a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c @@ -6,6 +6,7 @@ #include #include "gt/intel_gt.h" +#include "gt/intel_rps.h" #include "intel_guc_reg.h" #include "intel_huc.h" #include "intel_huc_print.h" @@ -447,17 +448,68 @@ static const char *auth_mode_string(struct intel_huc *huc, return partial ? "clear media" : "all workloads"; } +/* + * Use a longer timeout for debug builds so that problems can be detected + * and analysed. But a shorter timeout for releases so that user's don't + * wait forever to find out there is a problem. Note that the only reason + * an end user should hit the timeout is in case of extreme thermal throttling. + * And a system that is that hot during boot is probably dead anyway! + */ +#if defined(CONFIG_DRM_I915_DEBUG_GEM) +#define HUC_LOAD_RETRY_LIMIT 20 +#else +#define HUC_LOAD_RETRY_LIMIT 3 +#endif + int intel_huc_wait_for_auth_complete(struct intel_huc *huc, enum intel_huc_authentication_type type) { struct intel_gt *gt = huc_to_gt(huc); - int ret; + struct intel_uncore *uncore = gt->uncore; + ktime_t before, after, delta; + int ret, count; + u64
[PATCH v3 3/3] drm/i915/guc: Enable Wa_14019159160
From: John Harrison Use the new w/a KLV support to enable a MTL w/a. Note, this w/a is a super-set of Wa_16019325821, so requires turning that one as well as setting the new flag for Wa_14019159160 itself. Signed-off-by: John Harrison Reviewed-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 3 ++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 1 + drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 7 drivers/gpu/drm/i915/gt/uc/intel_guc.c| 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 34 ++- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 1 + 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index 9cccd60a5c41d..359b21fb02ab2 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -744,6 +744,7 @@ static u32 *gen12_emit_preempt_busywait(struct i915_request *rq, u32 *cs) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ #define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET 0x540 static u32 hold_switchout_semaphore_offset(struct i915_request *rq) { @@ -753,6 +754,7 @@ static u32 hold_switchout_semaphore_offset(struct i915_request *rq) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ static u32 *hold_switchout_emit_wa_busywait(struct i915_request *rq, u32 *cs) { int i; @@ -793,6 +795,7 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ + /* Wa_14019159160 */ if (intel_engine_uses_wa_hold_switchout(rq->engine)) cs = hold_switchout_emit_wa_busywait(rq, cs); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index b519812ba120d..ba55c059063db 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -697,6 +697,7 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ static inline bool intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine) { diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h index 58012edd4eb0e..bebf28e3c4794 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h @@ -101,4 +101,11 @@ enum { GUC_CONTEXT_POLICIES_KLV_NUM_IDS = 5, }; +/* + * Workaround keys: + */ +enum { + GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE = 0x9001, +}; + #endif /* _ABI_GUC_KLVS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index d5c856be31491..db3cb628f40dc 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -295,6 +295,7 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) flags |= GUC_WA_HOLD_CCS_SWITCHOUT; /* Wa_16019325821 */ + /* Wa_14019159160 */ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) flags |= GUC_WA_RCS_CCS_SWITCHOUT; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 251e7a7a05cb8..8f7298cbbc322 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -810,6 +810,25 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } +/* Wa_14019159160 */ +static u32 guc_waklv_ra_mode(struct intel_guc *guc, u32 offset, u32 remain) +{ + u32 size; + u32 klv_entry[] = { + /* 16:16 key/length */ + FIELD_PREP(GUC_KLV_0_KEY, GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE) | + FIELD_PREP(GUC_KLV_0_LEN, 0), + /* 0 dwords data */ + }; + + size = sizeof(klv_entry); + GEM_BUG_ON(remain < size); + + iosys_map_memcpy_to(>ads_map, offset, klv_entry, size); + + return size; +} + static void guc_waklv_init(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -825,15 +844,12 @@ static void guc_waklv_init(struct intel_guc *guc) offset = guc_ads_waklv_offset(guc); remain = guc_ads_waklv_size(guc); - /* -* Add workarounds here: -* -* if (want_wa_) { -* size = guc_waklv_(guc, offset, remain); -* offset += size; -* remain -= size; -* } -*/ + /* Wa_14019159160 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { + size = guc_waklv_ra_mode(guc, offset, remain); + offset += size; + remain -= size; + } size = guc_ads_waklv_size(guc) - remain; if (!size) diff --git
[PATCH v3 1/3] drm/i915: Enable Wa_16019325821
From: John Harrison Some platforms require holding RCS context switches until CCS is idle (the reverse w/a of Wa_14014475959). Some platforms require both versions. Signed-off-by: John Harrison Reviewed-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 19 +++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 7 --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 4 drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 3 ++- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 7 ++- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index 86a04afff64b3..9cccd60a5c41d 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -743,21 +743,23 @@ static u32 *gen12_emit_preempt_busywait(struct i915_request *rq, u32 *cs) } /* Wa_14014475959:dg2 */ -#define CCS_SEMAPHORE_PPHWSP_OFFSET0x540 -static u32 ccs_semaphore_offset(struct i915_request *rq) +/* Wa_16019325821 */ +#define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET 0x540 +static u32 hold_switchout_semaphore_offset(struct i915_request *rq) { return i915_ggtt_offset(rq->context->state) + - (LRC_PPHWSP_PN * PAGE_SIZE) + CCS_SEMAPHORE_PPHWSP_OFFSET; + (LRC_PPHWSP_PN * PAGE_SIZE) + HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET; } /* Wa_14014475959:dg2 */ -static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) +/* Wa_16019325821 */ +static u32 *hold_switchout_emit_wa_busywait(struct i915_request *rq, u32 *cs) { int i; *cs++ = MI_ATOMIC_INLINE | MI_ATOMIC_GLOBAL_GTT | MI_ATOMIC_CS_STALL | MI_ATOMIC_MOVE; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; *cs++ = 1; @@ -773,7 +775,7 @@ static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) MI_SEMAPHORE_POLL | MI_SEMAPHORE_SAD_EQ_SDD; *cs++ = 0; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; return cs; @@ -790,8 +792,9 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs) cs = gen12_emit_preempt_busywait(rq, cs); /* Wa_14014475959:dg2 */ - if (intel_engine_uses_wa_hold_ccs_switchout(rq->engine)) - cs = ccs_emit_wa_busywait(rq, cs); + /* Wa_16019325821 */ + if (intel_engine_uses_wa_hold_switchout(rq->engine)) + cs = hold_switchout_emit_wa_busywait(rq, cs); rq->tail = intel_ring_offset(rq, cs); assert_ring_tail_valid(rq->ring, rq->tail); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 960e6be2042fe..b519812ba120d 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -586,7 +586,7 @@ struct intel_engine_cs { #define I915_ENGINE_HAS_RCS_REG_STATE BIT(9) #define I915_ENGINE_HAS_EU_PRIORITYBIT(10) #define I915_ENGINE_FIRST_RENDER_COMPUTE BIT(11) -#define I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT BIT(12) +#define I915_ENGINE_USES_WA_HOLD_SWITCHOUT BIT(12) unsigned int flags; /* @@ -696,10 +696,11 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) } /* Wa_14014475959:dg2 */ +/* Wa_16019325821 */ static inline bool -intel_engine_uses_wa_hold_ccs_switchout(struct intel_engine_cs *engine) +intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine) { - return engine->flags & I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT; + return engine->flags & I915_ENGINE_USES_WA_HOLD_SWITCHOUT; } #endif /* __INTEL_ENGINE_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 2b450c43bbd7f..d5c856be31491 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -294,6 +294,10 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) IS_DG2(gt->i915)) flags |= GUC_WA_HOLD_CCS_SWITCHOUT; + /* Wa_16019325821 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) + flags |= GUC_WA_RCS_CCS_SWITCHOUT; + /* * Wa_14012197797 * Wa_22011391025 diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 8ae1846431da7..48863188a130e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -96,8 +96,9 @@ #define GUC_WA_GAM_CREDITS BIT(10) #define GUC_WA_DUAL_QUEUEBIT(11) #define GUC_WA_RCS_RESET_BEFORE_RC6 BIT(13) -#define GUC_WA_CONTEXT_ISOLATION BIT(15) #define GUC_WA_PRE_PARSERBIT(14) +#define GUC_WA_CONTEXT_ISOLATION BIT(15) +#define
[PATCH v3 2/3] drm/i915/guc: Add support for w/a KLVs
From: John Harrison To prevent running out of bits, new w/a enable flags are being added via a KLV system instead of a 32 bit flags word. Signed-off-by: John Harrison Reviewed-by: Vinay Belgaumkar --- .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 73 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 5 +- 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h index dabeaf4f245f3..00d6402333f8e 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h @@ -36,6 +36,7 @@ enum intel_guc_load_status { INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_START, INTEL_GUC_LOAD_STATUS_MPU_DATA_INVALID = 0x73, INTEL_GUC_LOAD_STATUS_INIT_MMIO_SAVE_RESTORE_INVALID = 0x74, + INTEL_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR= 0x75, INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_END, INTEL_GUC_LOAD_STATUS_READY= 0xF0, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index e22c12ce245ad..46b2d0e80b993 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -198,6 +198,8 @@ struct intel_guc { struct guc_mmio_reg *ads_regset; /** @ads_golden_ctxt_size: size of the golden contexts in the ADS */ u32 ads_golden_ctxt_size; + /** @ads_waklv_size: size of workaround KLVs */ + u32 ads_waklv_size; /** @ads_capture_size: size of register lists in the ADS used for error capture */ u32 ads_capture_size; /** @ads_engine_usage_size: size of engine usage in the ADS */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 63724e17829a7..251e7a7a05cb8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -46,6 +46,10 @@ * +---+ * | padding | * +---+ <== 4K aligned + * | w/a KLVs | + * +---+ + * | padding | + * +---+ <== 4K aligned * | capture lists | * +---+ * | padding | @@ -88,6 +92,11 @@ static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc) return PAGE_ALIGN(guc->ads_golden_ctxt_size); } +static u32 guc_ads_waklv_size(struct intel_guc *guc) +{ + return PAGE_ALIGN(guc->ads_waklv_size); +} + static u32 guc_ads_capture_size(struct intel_guc *guc) { return PAGE_ALIGN(guc->ads_capture_size); @@ -113,7 +122,7 @@ static u32 guc_ads_golden_ctxt_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } -static u32 guc_ads_capture_offset(struct intel_guc *guc) +static u32 guc_ads_waklv_offset(struct intel_guc *guc) { u32 offset; @@ -123,6 +132,16 @@ static u32 guc_ads_capture_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } +static u32 guc_ads_capture_offset(struct intel_guc *guc) +{ + u32 offset; + + offset = guc_ads_waklv_offset(guc) + +guc_ads_waklv_size(guc); + + return PAGE_ALIGN(offset); +} + static u32 guc_ads_private_data_offset(struct intel_guc *guc) { u32 offset; @@ -791,6 +810,49 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } +static void guc_waklv_init(struct intel_guc *guc) +{ + struct intel_gt *gt = guc_to_gt(guc); + u32 offset, addr_ggtt, remain, size; + + if (!intel_uc_uses_guc_submission(>uc)) + return; + + if (GUC_FIRMWARE_VER(guc) < MAKE_GUC_VER(70, 10, 0)) + return; + + GEM_BUG_ON(iosys_map_is_null(>ads_map)); + offset = guc_ads_waklv_offset(guc); + remain = guc_ads_waklv_size(guc); + + /* +* Add workarounds here: +* +* if (want_wa_) { +* size = guc_waklv_(guc, offset, remain); +* offset += size; +* remain -= size; +* } +*/ + + size = guc_ads_waklv_size(guc) - remain; + if (!size) + return; + + offset = guc_ads_waklv_offset(guc); + addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; + + ads_blob_write(guc, ads.wa_klv_addr_lo, addr_ggtt); + ads_blob_write(guc, ads.wa_klv_addr_hi, 0); + ads_blob_write(guc, ads.wa_klv_size, size); +} + +static int guc_prep_waklv(struct intel_guc
[PATCH v3 0/3] Enable Wa_14019159160 and Wa_16019325821 for MTL
From: John Harrison Enable Wa_14019159160 and Wa_16019325821 for MTL RCS/CCS workarounds for MTL. v2: Fix bug in WA KLV implementation (offset not being reset to start of list). Add better comment to prep patch about how KLVs can be added. Add a module parameter override and disable the w/a by default as it causes performance regressions and is only required by very specific workloads. v3: Rebase to latest tree. Drop module parameter as performance regression is apparently not detectable after all and a bunch of more common workloads have been seen to hit the issue. Signed-off-by: John Harrison John Harrison (3): drm/i915: Enable Wa_16019325821 drm/i915/guc: Add support for w/a KLVs drm/i915/guc: Enable Wa_14019159160 drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 22 +++-- drivers/gpu/drm/i915/gt/intel_engine_types.h | 8 +- .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 7 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.c| 5 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 89 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 8 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 8 +- 10 files changed, 141 insertions(+), 15 deletions(-) -- 2.41.0
[PATCH] drm/i915/guc: Avoid circular locking issue on busyness flush
From: John Harrison Avoid the following lockdep complaint: <4> [298.856498] == <4> [298.856500] WARNING: possible circular locking dependency detected <4> [298.856503] 6.7.0-rc5-CI_DRM_14017-g58ac4ffc75b6+ #1 Tainted: G N <4> [298.856505] -- <4> [298.856507] kworker/4:1H/190 is trying to acquire lock: <4> [298.856509] 8881103e9978 (>reset.backoff_srcu){}-{0:0}, at: _intel_gt_reset_lock+0x35/0x380 [i915] <4> [298.856661] but task is already holding lock: <4> [298.856663] c900013f7e58 ((work_completion)(&(>timestamp.work)->work)){+.+.}-{0:0}, at: process_scheduled_works+0x264/0x530 <4> [298.856671] which lock already depends on the new lock. The complaint is not actually valid. The busyness worker thread does indeed hold the worker lock and then attempt to acquire the reset lock (which may have happened in reverse order elsewhere). However, it does so with a trylock that exits if the reset lock is not available (specifically to prevent this and other similar deadlocks). Unfortunately, lockdep does not understand the trylock semantics (the lock is an i915 specific custom implementation for resets). Not doing a synchronous flush of the worker thread when a reset is in progress resolves the lockdep splat by never even attempting to grab the lock in this particular scenario. There are situatons where a synchronous cancel is required, however. So, always do the synchronous cancel if not in reset. And add an extra synchronous cancel to the end of the reset flow to account for when a reset is occurring at driver shutdown and the cancel is no longer synchronous but could lead to unallocated memory accesses if the worker is not stopped. Signed-off-by: Zhanjun Dong Signed-off-by: John Harrison Cc: Andi Shyti Cc: Daniel Vetter --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 48 ++- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 2 +- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index a259f1118c5ab..0228a77d456ed 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1362,7 +1362,45 @@ static void guc_enable_busyness_worker(struct intel_guc *guc) static void guc_cancel_busyness_worker(struct intel_guc *guc) { - cancel_delayed_work_sync(>timestamp.work); + /* +* There are many different call stacks that can get here. Some of them +* hold the reset mutex. The busyness worker also attempts to acquire the +* reset mutex. Synchronously flushing a worker thread requires acquiring +* the worker mutex. Lockdep sees this as a conflict. It thinks that the +* flush can deadlock because it holds the worker mutex while waiting for +* the reset mutex, but another thread is holding the reset mutex and might +* attempt to use other worker functions. +* +* In practice, this scenario does not exist because the busyness worker +* does not block waiting for the reset mutex. It does a try-lock on it and +* immediately exits if the lock is already held. Unfortunately, the mutex +* in question (I915_RESET_BACKOFF) is an i915 implementation which has lockdep +* annotation but not to the extent of explaining the 'might lock' is also a +* 'does not need to lock'. So one option would be to add more complex lockdep +* annotations to ignore the issue (if at all possible). A simpler option is to +* just not flush synchronously when a rest in progress. Given that the worker +* will just early exit and re-schedule itself anyway, there is no advantage +* to running it immediately. +* +* If a reset is not in progress, then the synchronous flush may be required. +* As noted many call stacks lead here, some during suspend and driver unload +* which do require a synchronous flush to make sure the worker is stopped +* before memory is freed. +* +* Trying to pass a 'need_sync' or 'in_reset' flag all the way down through +* every possible call stack is unfeasible. It would be too intrusive to many +* areas that really don't care about the GuC backend. However, there is the +* 'reset_in_progress' flag available, so just use that. +* +* And note that in the case of a reset occurring during driver unload +* (wedge_on_fini), skipping the cancel in _prepare (when the reset flag is set +* is fine because there is another cancel in _finish (when the reset flag is +* not). +*/ + if (guc_to_gt(guc)->uc.reset_in_progress) + cancel_delayed_work(>timestamp.work); + else +
[Intel-gfx] [PATCH v2 1/2] drm/i915/guc: Fix for potential false positives in GuC hang selftest
From: John Harrison Noticed that the hangcheck selftest is submitting a non-preemptoble spinner. That means that even if the GuC does not die, the heartbeat will still kick in and trigger a reset. Which is rather defeating the purpose of the test - to verify that the heartbeat will kick in if the GuC itself has died. The test is deliberately killing the GuC, so it should never hit the case of a non-dead GuC. But it is not impossible that the kill might fail at some future point due to other driver re-work. So, make the spinner pre-emptible. That way the heartbeat can get through if the GuC is alive and context switching. Thus a reset only happens if the GuC dies. Thus, if the kill should stop working the test will now fail rather than claim to pass. Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c index 34b5d952e2bcb..26fdc392fce6c 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c @@ -74,7 +74,7 @@ static int intel_hang_guc(void *arg) goto err; } - rq = igt_spinner_create_request(, ce, MI_NOOP); + rq = igt_spinner_create_request(, ce, MI_ARB_CHECK); intel_context_put(ce); if (IS_ERR(rq)) { ret = PTR_ERR(rq); -- 2.41.0
[Intel-gfx] [PATCH v2 2/2] drm/i915/guc: Add a selftest for FAST_REQUEST errors
From: John Harrison There is a mechanism for reporting errors from fire and forget H2G messages. This is the only way to find out about almost any error in the GuC backend submission path. So it would be useful to know that it is working. v2: Fix some dumb over-complications and a couple of typos - review feedback from Daniele. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc.h| 4 + drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 9 ++ drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 115 ++ 3 files changed, 128 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 2b6dfe62c8f2a..e22c12ce245ad 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -297,6 +297,10 @@ struct intel_guc { * @number_guc_id_stolen: The number of guc_ids that have been stolen */ int number_guc_id_stolen; + /** +* @fast_response_selftest: Backdoor to CT handler for fast response selftest +*/ + u32 fast_response_selftest; #endif }; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index 89e314b3756bb..ed6ce73ef3b07 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -1076,6 +1076,15 @@ static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *r found = true; break; } + +#ifdef CONFIG_DRM_I915_SELFTEST + if (!found && ct_to_guc(ct)->fast_response_selftest) { + CT_DEBUG(ct, "Assuming unsolicited response due to FAST_REQUEST selftest\n"); + ct_to_guc(ct)->fast_response_selftest++; + found = true; + } +#endif + if (!found) { CT_ERROR(ct, "Unsolicited response message: len %u, data %#x (fence %u, last %u)\n", len, hxg[0], fence, ct->requests.last_fence); diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c index bfb72143566f6..c900aac85adba 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c @@ -286,11 +286,126 @@ static int intel_guc_steal_guc_ids(void *arg) return ret; } +/* + * Send a context schedule H2G message with an invalid context id. + * This should generate a GUC_RESULT_INVALID_CONTEXT response. + */ +static int bad_h2g(struct intel_guc *guc) +{ + u32 action[] = { + INTEL_GUC_ACTION_SCHED_CONTEXT, + 0x12345678, + }; + + return intel_guc_send_nb(guc, action, ARRAY_SIZE(action), 0); +} + +/* + * Set a spinner running to make sure the system is alive and active, + * then send a bad but asynchronous H2G command and wait to see if an + * error response is returned. If no response is received or if the + * spinner dies then the test will fail. + */ +#define FAST_RESPONSE_TIMEOUT_MS 1000 +static int intel_guc_fast_request(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_context *ce; + struct igt_spinner spin; + struct i915_request *rq; + intel_wakeref_t wakeref; + struct intel_engine_cs *engine = intel_selftest_find_any_engine(gt); + bool spinning = false; + int ret = 0; + + if (!engine) + return 0; + + wakeref = intel_runtime_pm_get(gt->uncore->rpm); + + ce = intel_context_create(engine); + if (IS_ERR(ce)) { + ret = PTR_ERR(ce); + gt_err(gt, "Failed to create spinner request: %pe\n", ce); + goto err_pm; + } + + ret = igt_spinner_init(, engine->gt); + if (ret) { + gt_err(gt, "Failed to create spinner: %pe\n", ERR_PTR(ret)); + goto err_pm; + } + spinning = true; + + rq = igt_spinner_create_request(, ce, MI_ARB_CHECK); + intel_context_put(ce); + if (IS_ERR(rq)) { + ret = PTR_ERR(rq); + gt_err(gt, "Failed to create spinner request: %pe\n", rq); + goto err_spin; + } + + ret = request_add_spin(rq, ); + if (ret) { + gt_err(gt, "Failed to add Spinner request: %pe\n", ERR_PTR(ret)); + goto err_rq; + } + + gt->uc.guc.fast_response_selftest = 1; + + ret = bad_h2g(>uc.guc); + if (ret) { + gt_err(gt, "Failed to send H2G: %pe\n", ERR_PTR(ret)); + goto err_rq; + } + + ret = wait_for(gt->uc.guc.fast_response_selftest != 1 || i915_request_completed(rq), + FAST_RESPONSE_TIMEOUT_MS); + if (ret) { + gt_err(gt, "Request wait failed: %pe\n", ERR_PTR(ret)); + goto err_rq; + } + + if (i915_request_completed(rq)) { + gt_err(gt, "Spinner died waiting for fast request error!\n"); +
[Intel-gfx] [PATCH v2 0/2] Selftest for FAST_REQUEST feature
From: John Harrison Add a selftest to verify that the FAST_REQUEST mechanism (getting errors back from fire-and-forget H2G commands) is functional. Also fix up a potential false positive in the GuC hang selftest. v2: Fix some dumb over-complications and typos - review feedback from Daniele. Signed-off-by: John Harrison John Harrison (2): drm/i915/guc: Fix for potential false positives in GuC hang selftest drm/i915/guc: Add a selftest for FAST_REQUEST errors drivers/gpu/drm/i915/gt/uc/intel_guc.h| 4 + drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 9 ++ drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 115 ++ .../drm/i915/gt/uc/selftest_guc_hangcheck.c | 2 +- 4 files changed, 129 insertions(+), 1 deletion(-) -- 2.41.0
[Intel-gfx] [PATCH 1/2] drm/i915/guc: Don't double enable a context
From: John Harrison If a context is blocked, unblocked and subitted repeatedly in rapid succession, the driver can end up trying to enable the context while the previous enable request is still in flight. This can lead to much confusion in the state tracking. Prevent that by checking the pending enable flag before trying to enable a context. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index d37698bd6b91a..d399e4d238c10 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -720,7 +720,7 @@ static int __guc_add_request(struct intel_guc *guc, struct i915_request *rq) if (unlikely(context_blocked(ce) && !intel_context_is_parent(ce))) goto out; - enabled = context_enabled(ce) || context_blocked(ce); + enabled = context_enabled(ce) || context_blocked(ce) || context_pending_enable(ce); if (!enabled) { action[len++] = INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_SET; -- 2.41.0
[Intel-gfx] [PATCH 2/2] drm/i915/guc: Don't disable a context whose enable is still pending
From: John Harrison Various processes involve requesting GuC to disable a given context. However context enable/disable is an asynchronous process in the GuC. Thus, it is possible the previous enable request is still being processed when the disable request is triggered. Having both enable and disable in flight concurrently is illegal - GuC will return an error and fail the second operation. The KMD side handler for the completion message also can't cope with having both pending flags set. So delay the disable request until it is safe to send. Signed-off-by: John Harrison --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 31 +++ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index d399e4d238c10..8c34b0a5abf9a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -3150,7 +3150,8 @@ guc_context_revoke(struct intel_context *ce, struct i915_request *rq, guc_cancel_context_requests(ce); intel_engine_signal_breadcrumbs(ce->engine); } else if (!context_pending_disable(ce)) { - u16 guc_id; + u16 guc_id = ~0; + bool pending_enable = context_pending_enable(ce); /* * We add +2 here as the schedule disable complete CTB handler @@ -3158,7 +3159,11 @@ guc_context_revoke(struct intel_context *ce, struct i915_request *rq, */ atomic_add(2, >pin_count); - guc_id = prep_context_pending_disable(ce); + if (pending_enable) + guc_id = ce->guc_id.id; + else + guc_id = prep_context_pending_disable(ce); + spin_unlock_irqrestore(>guc_state.lock, flags); /* @@ -3169,7 +3174,15 @@ guc_context_revoke(struct intel_context *ce, struct i915_request *rq, with_intel_runtime_pm(runtime_pm, wakeref) { __guc_context_set_preemption_timeout(guc, guc_id, preempt_timeout_ms); - __guc_context_sched_disable(guc, ce, guc_id); + if (!pending_enable) + __guc_context_sched_disable(guc, ce, guc_id); + } + + if (pending_enable) { + /* Can't have both in flight concurrently, so try again later... */ + mod_delayed_work(system_unbound_wq, + >guc_state.sched_disable_delay_work, +msecs_to_jiffies(1)); } } else { if (!context_guc_id_invalid(ce)) @@ -3222,7 +3235,13 @@ static void __delay_sched_disable(struct work_struct *wrk) spin_lock_irqsave(>guc_state.lock, flags); - if (bypass_sched_disable(guc, ce)) { + if (context_pending_enable(ce)) { + spin_unlock_irqrestore(>guc_state.lock, flags); + /* Can't have both in flight concurrently, so try again later... */ + mod_delayed_work(system_unbound_wq, +>guc_state.sched_disable_delay_work, +msecs_to_jiffies(1)); + } else if (bypass_sched_disable(guc, ce)) { spin_unlock_irqrestore(>guc_state.lock, flags); intel_context_sched_disable_unpin(ce); } else { @@ -3257,8 +3276,8 @@ static void guc_context_sched_disable(struct intel_context *ce) if (bypass_sched_disable(guc, ce)) { spin_unlock_irqrestore(>guc_state.lock, flags); intel_context_sched_disable_unpin(ce); - } else if (!intel_context_is_closed(ce) && !guc_id_pressure(guc, ce) && - delay) { + } else if ((!intel_context_is_closed(ce) && !guc_id_pressure(guc, ce) && + delay) || context_pending_enable(ce)) { spin_unlock_irqrestore(>guc_state.lock, flags); mod_delayed_work(system_unbound_wq, >guc_state.sched_disable_delay_work, -- 2.41.0
[Intel-gfx] [PATCH 0/2] Don't send double context enable/disable requests
From: John Harrison The driver could sometimes send context enable/disable requests when a previous request was still pending. This is not allowed. So stop doing it. Signed-off-by: John Harrison John Harrison (2): drm/i915/guc: Don't double enable a context drm/i915/guc: Don't disable a context whose enable is still pending .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 33 +++ 1 file changed, 26 insertions(+), 7 deletions(-) -- 2.41.0
[Intel-gfx] [PATCH 2/2] drm/i915/guc: Add a selftest for FAST_REQUEST errors
From: John Harrison There is a mechanism for reporting errors from fire and forget H2G messages. This is the only way to find out about almost any error in the GuC backend submission path. So it would be useful to know that it is working. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc.h| 4 + drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 9 ++ drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 122 ++ 3 files changed, 135 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 2b6dfe62c8f2a..e22c12ce245ad 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -297,6 +297,10 @@ struct intel_guc { * @number_guc_id_stolen: The number of guc_ids that have been stolen */ int number_guc_id_stolen; + /** +* @fast_response_selftest: Backdoor to CT handler for fast response selftest +*/ + u32 fast_response_selftest; #endif }; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index 89e314b3756bb..9d958afb78b7f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -1076,6 +1076,15 @@ static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *r found = true; break; } + +#ifdef CONFIG_DRM_I915_SELFTEST + if (!found && ct_to_guc(ct)->fast_response_selftest) { + CT_DEBUG(ct, "Assuming unsolicited response due to FAST_REQUEST selftest\n"); + ct_to_guc(ct)->fast_response_selftest++; + found = 1; + } +#endif + if (!found) { CT_ERROR(ct, "Unsolicited response message: len %u, data %#x (fence %u, last %u)\n", len, hxg[0], fence, ct->requests.last_fence); diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c index bfb72143566f6..97fbbb396336c 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c @@ -286,11 +286,133 @@ static int intel_guc_steal_guc_ids(void *arg) return ret; } +/* + * Send a context schedule H2G message with an invalid context id. + * This should generate a GUC_RESULT_INVALID_CONTEXT response. + */ +static int bad_h2g(struct intel_guc *guc) +{ + u32 action[3], len = 0; + + action[len++] = INTEL_GUC_ACTION_SCHED_CONTEXT; + action[len++] = 0x12345678; + + return intel_guc_send_nb(guc, action, len, 0); +} + +/* + * Set a spinner running to make sure the system is alive and active, + * then send a bad but asynchronous H2G command and wait to see if an + * error response is returned. If no response is received or if the + * spinner dies then the test will fail. + */ +#define FAST_RESPONSE_TIMEOUT_MS 1000 +static int intel_guc_fast_request(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_context *ce; + struct igt_spinner spin; + struct i915_request *rq; + intel_wakeref_t wakeref; + struct intel_engine_cs *engine = intel_selftest_find_any_engine(gt); + ktime_t before, now, delta; + bool spinning = false; + u64 delta_ms; + int ret = 0; + + if (!engine) + return 0; + + wakeref = intel_runtime_pm_get(gt->uncore->rpm); + + ce = intel_context_create(engine); + if (IS_ERR(ce)) { + ret = PTR_ERR(ce); + gt_err(gt, "Failed to create spinner request: %pe\n", ce); + goto err_pm; + } + + ret = igt_spinner_init(, engine->gt); + if (ret) { + gt_err(gt, "Failed to create spinner: %pe\n", ERR_PTR(ret)); + goto err_pm; + } + spinning = true; + + rq = igt_spinner_create_request(, ce, MI_ARB_CHECK); + intel_context_put(ce); + if (IS_ERR(rq)) { + ret = PTR_ERR(rq); + gt_err(gt, "Failed to create spinner request: %pe\n", rq); + goto err_spin; + } + + ret = request_add_spin(rq, ); + if (ret) { + gt_err(gt, "Failed to add Spinner request: %pe\n", ERR_PTR(ret)); + goto err_rq; + } + + gt->uc.guc.fast_response_selftest = 1; + + ret = bad_h2g(>uc.guc); + if (ret) { + gt_err(gt, "Failed to send H2G: %pe\n", ERR_PTR(ret)); + goto err_rq; + } + + before = ktime_get(); + while (gt->uc.guc.fast_response_selftest == 1) { + ret = i915_request_wait(rq, 0, 1); + if (ret != -ETIME) { + gt_err(gt, "Request wait failed: %pe\n", ERR_PTR(ret)); + goto err_rq; + } + now = ktime_get(); + delta = ktime_sub(now, before); + delta_ms = ktime_to_ms(delta); +
[Intel-gfx] [PATCH 1/2] drm/i915/guc: Fix for potential false positives in GuC hang selftest
From: John Harrison Noticed that the hangcheck selftest is submitting a non-preemptoble spinner. That means that even if the GuC does not die, the heartbeat will still kick in and trigger a reset. Which is rather defeating the purpose of the test - to verify that the heartbeat will kick in if the GuC itself has died. The test is deliberately killing the GuC, so it should never hit the case of a non-dead GuC. But it is not impossible that the kill might fail at some future point due to other driver re-work. So, make the spinner pre-emptible. That way the heartbeat can get through if the GuC is alive and context switching. Thus a reset only happens if the GuC dies. Thus, if the kill should stop working the test will now fail rather than claim to pass. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c index 34b5d952e2bcb..26fdc392fce6c 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c @@ -74,7 +74,7 @@ static int intel_hang_guc(void *arg) goto err; } - rq = igt_spinner_create_request(, ce, MI_NOOP); + rq = igt_spinner_create_request(, ce, MI_ARB_CHECK); intel_context_put(ce); if (IS_ERR(rq)) { ret = PTR_ERR(rq); -- 2.41.0
[Intel-gfx] [PATCH 0/2] Selftest for FAST_REQUEST feature
From: John Harrison Add a selftest to verify that the FAST_REQUEST mechanism (getting errors back from fire-and-forget H2G commands) is functional. Also fix up a potential false positive in the GuC hang selftest. Signed-off-by: John Harrison John Harrison (2): drm/i915/guc: Fix for potential false positives in GuC hang selftest drm/i915/guc: Add a selftest for FAST_REQUEST errors drivers/gpu/drm/i915/gt/uc/intel_guc.h| 4 + drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 9 ++ drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 122 ++ .../drm/i915/gt/uc/selftest_guc_hangcheck.c | 2 +- 4 files changed, 136 insertions(+), 1 deletion(-) -- 2.41.0
[Intel-gfx] [PATCH v2 2/4] drm/i915/guc: Add support for w/a KLVs
From: John Harrison To prevent running out of bits, new w/a enable flags are being added via a KLV system instead of a 32 bit flags word. Signed-off-by: John Harrison --- .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 73 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 5 +- 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h index dabeaf4f245f3..00d6402333f8e 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h @@ -36,6 +36,7 @@ enum intel_guc_load_status { INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_START, INTEL_GUC_LOAD_STATUS_MPU_DATA_INVALID = 0x73, INTEL_GUC_LOAD_STATUS_INIT_MMIO_SAVE_RESTORE_INVALID = 0x74, + INTEL_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR= 0x75, INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_END, INTEL_GUC_LOAD_STATUS_READY= 0xF0, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 2b6dfe62c8f2a..4113776ff3e19 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -198,6 +198,8 @@ struct intel_guc { struct guc_mmio_reg *ads_regset; /** @ads_golden_ctxt_size: size of the golden contexts in the ADS */ u32 ads_golden_ctxt_size; + /** @ads_waklv_size: size of workaround KLVs */ + u32 ads_waklv_size; /** @ads_capture_size: size of register lists in the ADS used for error capture */ u32 ads_capture_size; /** @ads_engine_usage_size: size of engine usage in the ADS */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 63724e17829a7..251e7a7a05cb8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -46,6 +46,10 @@ * +---+ * | padding | * +---+ <== 4K aligned + * | w/a KLVs | + * +---+ + * | padding | + * +---+ <== 4K aligned * | capture lists | * +---+ * | padding | @@ -88,6 +92,11 @@ static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc) return PAGE_ALIGN(guc->ads_golden_ctxt_size); } +static u32 guc_ads_waklv_size(struct intel_guc *guc) +{ + return PAGE_ALIGN(guc->ads_waklv_size); +} + static u32 guc_ads_capture_size(struct intel_guc *guc) { return PAGE_ALIGN(guc->ads_capture_size); @@ -113,7 +122,7 @@ static u32 guc_ads_golden_ctxt_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } -static u32 guc_ads_capture_offset(struct intel_guc *guc) +static u32 guc_ads_waklv_offset(struct intel_guc *guc) { u32 offset; @@ -123,6 +132,16 @@ static u32 guc_ads_capture_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } +static u32 guc_ads_capture_offset(struct intel_guc *guc) +{ + u32 offset; + + offset = guc_ads_waklv_offset(guc) + +guc_ads_waklv_size(guc); + + return PAGE_ALIGN(offset); +} + static u32 guc_ads_private_data_offset(struct intel_guc *guc) { u32 offset; @@ -791,6 +810,49 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } +static void guc_waklv_init(struct intel_guc *guc) +{ + struct intel_gt *gt = guc_to_gt(guc); + u32 offset, addr_ggtt, remain, size; + + if (!intel_uc_uses_guc_submission(>uc)) + return; + + if (GUC_FIRMWARE_VER(guc) < MAKE_GUC_VER(70, 10, 0)) + return; + + GEM_BUG_ON(iosys_map_is_null(>ads_map)); + offset = guc_ads_waklv_offset(guc); + remain = guc_ads_waklv_size(guc); + + /* +* Add workarounds here: +* +* if (want_wa_) { +* size = guc_waklv_(guc, offset, remain); +* offset += size; +* remain -= size; +* } +*/ + + size = guc_ads_waklv_size(guc) - remain; + if (!size) + return; + + offset = guc_ads_waklv_offset(guc); + addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; + + ads_blob_write(guc, ads.wa_klv_addr_lo, addr_ggtt); + ads_blob_write(guc, ads.wa_klv_addr_hi, 0); + ads_blob_write(guc, ads.wa_klv_size, size); +} + +static int guc_prep_waklv(struct intel_guc *guc) +{ + /* Fudge
[Intel-gfx] [PATCH v2 4/4] drm/i915/mtl: Add module parameter override for Wa_16019325821/Wa_14019159160
From: John Harrison These w/a's can have signficant performance implications for any workload which uses both RCS and CCS. On the other hand, the hang itself is only seen in one or two very specific workloads. So add a module parameter to control whether the w/a's are enabled or not and default to not. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 3 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 3 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 3 ++- drivers/gpu/drm/i915/i915_params.c| 3 +++ drivers/gpu/drm/i915/i915_params.h| 1 + 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 6252f32d67011..4c89983b1e907 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -296,7 +296,8 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) /* Wa_16019325821 */ /* Wa_14019159160 */ - if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) + if (gt->i915->params.enable_mtl_rcs_ccs_wa && + IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) flags |= GUC_WA_RCS_CCS_SWITCHOUT; /* diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 8f7298cbbc322..78757e78bce88 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -845,7 +845,8 @@ static void guc_waklv_init(struct intel_guc *guc) remain = guc_ads_waklv_size(guc); /* Wa_14019159160 */ - if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { + if (gt->i915->params.enable_mtl_rcs_ccs_wa && + IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { size = guc_waklv_ra_mode(guc, offset, remain); offset += size; remain -= size; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 225812b299524..4de54a100c451 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4384,7 +4384,8 @@ static void guc_default_vfuncs(struct intel_engine_cs *engine) /* Wa_16019325821 */ /* Wa_14019159160 */ - if ((engine->class == COMPUTE_CLASS || engine->class == RENDER_CLASS) && + if (engine->i915->params.enable_mtl_rcs_ccs_wa && + (engine->class == COMPUTE_CLASS || engine->class == RENDER_CLASS) && IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 71))) engine->flags |= I915_ENGINE_USES_WA_HOLD_SWITCHOUT; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index de43048543e8b..1004171d99943 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -134,6 +134,9 @@ i915_param_named_unsafe(lmem_size, uint, 0400, i915_param_named_unsafe(lmem_bar_size, uint, 0400, "Set the lmem bar size(in MiB)."); +i915_param_named(enable_mtl_rcs_ccs_wa, bool, 0400, + "Enable the RCS/CCS switchout hold workaround for MTL (only some workloads are affected by issue and w/a has a performance penalty) (default:false)"); + static void _param_print_bool(struct drm_printer *p, const char *name, bool val) { diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 1315d7fac850f..971a765d74f56 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -62,6 +62,7 @@ struct drm_printer; param(unsigned int, lmem_size, 0, 0400) \ param(unsigned int, lmem_bar_size, 0, 0400) \ /* leave bools at the end to not create holes */ \ + param(bool, enable_mtl_rcs_ccs_wa, false, 0x400) \ param(bool, enable_hangcheck, true, 0600) \ param(bool, error_capture, true, IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) ? 0600 : 0) \ param(bool, enable_gvt, false, IS_ENABLED(CONFIG_DRM_I915_GVT) ? 0400 : 0) -- 2.41.0
[Intel-gfx] [PATCH v2 3/4] drm/i915/guc: Enable Wa_14019159160
From: John Harrison Use the new w/a KLV support to enable a MTL w/a. Note, this w/a is a super-set of Wa_16019325821, so requires turning that one as well as setting the new flag for Wa_14019159160 itself. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 3 ++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 1 + drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 7 drivers/gpu/drm/i915/gt/uc/intel_guc.c| 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 34 ++- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 1 + 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index 9cccd60a5c41d..359b21fb02ab2 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -744,6 +744,7 @@ static u32 *gen12_emit_preempt_busywait(struct i915_request *rq, u32 *cs) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ #define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET 0x540 static u32 hold_switchout_semaphore_offset(struct i915_request *rq) { @@ -753,6 +754,7 @@ static u32 hold_switchout_semaphore_offset(struct i915_request *rq) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ static u32 *hold_switchout_emit_wa_busywait(struct i915_request *rq, u32 *cs) { int i; @@ -793,6 +795,7 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ + /* Wa_14019159160 */ if (intel_engine_uses_wa_hold_switchout(rq->engine)) cs = hold_switchout_emit_wa_busywait(rq, cs); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index f08739d020332..3b4993955a4b6 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -695,6 +695,7 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ static inline bool intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine) { diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h index 58012edd4eb0e..bebf28e3c4794 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h @@ -101,4 +101,11 @@ enum { GUC_CONTEXT_POLICIES_KLV_NUM_IDS = 5, }; +/* + * Workaround keys: + */ +enum { + GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE = 0x9001, +}; + #endif /* _ABI_GUC_KLVS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 0e6c160de3315..6252f32d67011 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -295,6 +295,7 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) flags |= GUC_WA_HOLD_CCS_SWITCHOUT; /* Wa_16019325821 */ + /* Wa_14019159160 */ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) flags |= GUC_WA_RCS_CCS_SWITCHOUT; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 251e7a7a05cb8..8f7298cbbc322 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -810,6 +810,25 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } +/* Wa_14019159160 */ +static u32 guc_waklv_ra_mode(struct intel_guc *guc, u32 offset, u32 remain) +{ + u32 size; + u32 klv_entry[] = { + /* 16:16 key/length */ + FIELD_PREP(GUC_KLV_0_KEY, GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE) | + FIELD_PREP(GUC_KLV_0_LEN, 0), + /* 0 dwords data */ + }; + + size = sizeof(klv_entry); + GEM_BUG_ON(remain < size); + + iosys_map_memcpy_to(>ads_map, offset, klv_entry, size); + + return size; +} + static void guc_waklv_init(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -825,15 +844,12 @@ static void guc_waklv_init(struct intel_guc *guc) offset = guc_ads_waklv_offset(guc); remain = guc_ads_waklv_size(guc); - /* -* Add workarounds here: -* -* if (want_wa_) { -* size = guc_waklv_(guc, offset, remain); -* offset += size; -* remain -= size; -* } -*/ + /* Wa_14019159160 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { + size = guc_waklv_ra_mode(guc, offset, remain); + offset += size; + remain -= size; + } size = guc_ads_waklv_size(guc) - remain; if (!size) diff --git
[Intel-gfx] [PATCH v2 1/4] drm/i915: Enable Wa_16019325821
From: John Harrison Some platforms require holding RCS context switches until CCS is idle (the reverse w/a of Wa_14014475959). Some platforms require both versions. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 19 +++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 7 --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 4 drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 3 ++- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 7 ++- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index 86a04afff64b3..9cccd60a5c41d 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -743,21 +743,23 @@ static u32 *gen12_emit_preempt_busywait(struct i915_request *rq, u32 *cs) } /* Wa_14014475959:dg2 */ -#define CCS_SEMAPHORE_PPHWSP_OFFSET0x540 -static u32 ccs_semaphore_offset(struct i915_request *rq) +/* Wa_16019325821 */ +#define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET 0x540 +static u32 hold_switchout_semaphore_offset(struct i915_request *rq) { return i915_ggtt_offset(rq->context->state) + - (LRC_PPHWSP_PN * PAGE_SIZE) + CCS_SEMAPHORE_PPHWSP_OFFSET; + (LRC_PPHWSP_PN * PAGE_SIZE) + HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET; } /* Wa_14014475959:dg2 */ -static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) +/* Wa_16019325821 */ +static u32 *hold_switchout_emit_wa_busywait(struct i915_request *rq, u32 *cs) { int i; *cs++ = MI_ATOMIC_INLINE | MI_ATOMIC_GLOBAL_GTT | MI_ATOMIC_CS_STALL | MI_ATOMIC_MOVE; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; *cs++ = 1; @@ -773,7 +775,7 @@ static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) MI_SEMAPHORE_POLL | MI_SEMAPHORE_SAD_EQ_SDD; *cs++ = 0; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; return cs; @@ -790,8 +792,9 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs) cs = gen12_emit_preempt_busywait(rq, cs); /* Wa_14014475959:dg2 */ - if (intel_engine_uses_wa_hold_ccs_switchout(rq->engine)) - cs = ccs_emit_wa_busywait(rq, cs); + /* Wa_16019325821 */ + if (intel_engine_uses_wa_hold_switchout(rq->engine)) + cs = hold_switchout_emit_wa_busywait(rq, cs); rq->tail = intel_ring_offset(rq, cs); assert_ring_tail_valid(rq->ring, rq->tail); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 8769760257fd9..f08739d020332 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -584,7 +584,7 @@ struct intel_engine_cs { #define I915_ENGINE_HAS_RCS_REG_STATE BIT(9) #define I915_ENGINE_HAS_EU_PRIORITYBIT(10) #define I915_ENGINE_FIRST_RENDER_COMPUTE BIT(11) -#define I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT BIT(12) +#define I915_ENGINE_USES_WA_HOLD_SWITCHOUT BIT(12) unsigned int flags; /* @@ -694,10 +694,11 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) } /* Wa_14014475959:dg2 */ +/* Wa_16019325821 */ static inline bool -intel_engine_uses_wa_hold_ccs_switchout(struct intel_engine_cs *engine) +intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine) { - return engine->flags & I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT; + return engine->flags & I915_ENGINE_USES_WA_HOLD_SWITCHOUT; } #endif /* __INTEL_ENGINE_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 3f3df1166b860..0e6c160de3315 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -294,6 +294,10 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) IS_DG2(gt->i915)) flags |= GUC_WA_HOLD_CCS_SWITCHOUT; + /* Wa_16019325821 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) + flags |= GUC_WA_RCS_CCS_SWITCHOUT; + /* * Wa_14012197797 * Wa_22011391025 diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 8ae1846431da7..48863188a130e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -96,8 +96,9 @@ #define GUC_WA_GAM_CREDITS BIT(10) #define GUC_WA_DUAL_QUEUEBIT(11) #define GUC_WA_RCS_RESET_BEFORE_RC6 BIT(13) -#define GUC_WA_CONTEXT_ISOLATION BIT(15) #define GUC_WA_PRE_PARSERBIT(14) +#define GUC_WA_CONTEXT_ISOLATION BIT(15) +#define GUC_WA_RCS_CCS_SWITCHOUT
[Intel-gfx] [PATCH v2 0/4] Enable Wa_14019159160 and Wa_16019325821 for MTL
From: John Harrison Enable Wa_14019159160 and Wa_16019325821 for MTL RCS/CCS workarounds for MTL. v2: Fix bug in WA KLV implementation (offset not being reset to start of list). Add better comment to prep patch about how KLVs can be added. Add a module parameter override and disable the w/a by default as it causes performance regressions and is only required by very specific workloads. Signed-off-by: John Harrison John Harrison (4): drm/i915: Enable Wa_16019325821 drm/i915/guc: Add support for w/a KLVs drm/i915/guc: Enable Wa_14019159160 drm/i915/mtl: Add module parameter override for Wa_16019325821/Wa_14019159160 drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 22 +++-- drivers/gpu/drm/i915/gt/intel_engine_types.h | 8 +- .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 7 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.c| 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 90 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 8 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 9 +- drivers/gpu/drm/i915/i915_params.c| 3 + drivers/gpu/drm/i915/i915_params.h| 1 + 12 files changed, 148 insertions(+), 15 deletions(-) -- 2.41.0
[Intel-gfx] PR for new GuC v70.13.1
The following changes since commit 7727f7e3b3358713c7c91c64a835e80c331a6b8b: Merge branch 'patch-1696561325' into 'main' (2023-10-06 03:04:57 +) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm-firmware guc_70.13.1 for you to fetch changes up to 44a9510c94ac0334931b6c89dd240ffe5bf1e5fa: i915: Add GuC v70.13.1 for DG2, TGL, ADL-P and MTL (2023-10-13 11:34:26 -0700) John Harrison (1): i915: Add GuC v70.13.1 for DG2, TGL, ADL-P and MTL WHENCE | 8 i915/adlp_guc_70.bin | Bin 297984 -> 342848 bytes i915/dg2_guc_70.bin | Bin 385856 -> 443200 bytes i915/mtl_guc_70.bin | Bin 308032 -> 365376 bytes i915/tgl_guc_70.bin | Bin 285888 -> 330304 bytes 5 files changed, 4 insertions(+), 4 deletions(-)
[Intel-gfx] [CI] PR for new GuC v70.13.1
The following changes since commit 7727f7e3b3358713c7c91c64a835e80c331a6b8b: Merge branch 'patch-1696561325' into 'main' (2023-10-06 03:04:57 +) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm-firmware guc_70.13.1 for you to fetch changes up to 44a9510c94ac0334931b6c89dd240ffe5bf1e5fa: i915: Add GuC v70.13.1 for DG2, TGL, ADL-P and MTL (2023-10-13 11:34:26 -0700) John Harrison (1): i915: Add GuC v70.13.1 for DG2, TGL, ADL-P and MTL WHENCE | 8 i915/adlp_guc_70.bin | Bin 297984 -> 342848 bytes i915/dg2_guc_70.bin | Bin 385856 -> 443200 bytes i915/mtl_guc_70.bin | Bin 308032 -> 365376 bytes i915/tgl_guc_70.bin | Bin 285888 -> 330304 bytes 5 files changed, 4 insertions(+), 4 deletions(-)
[Intel-gfx] [CI] PR for new GuC v70.13.1
The following changes since commit 7727f7e3b3358713c7c91c64a835e80c331a6b8b: Merge branch 'patch-1696561325' into 'main' (2023-10-06 03:04:57 +) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm-firmware guc_70.13.1 for you to fetch changes up to 44a9510c94ac0334931b6c89dd240ffe5bf1e5fa: i915: Add GuC v70.13.1 for DG2, TGL, ADL-P and MTL (2023-10-13 11:34:26 -0700) John Harrison (1): i915: Add GuC v70.13.1 for DG2, TGL, ADL-P and MTL WHENCE | 8 i915/adlp_guc_70.bin | Bin 297984 -> 342848 bytes i915/dg2_guc_70.bin | Bin 385856 -> 443200 bytes i915/mtl_guc_70.bin | Bin 308032 -> 365376 bytes i915/tgl_guc_70.bin | Bin 285888 -> 330304 bytes 5 files changed, 4 insertions(+), 4 deletions(-)
[Intel-gfx] [PATCH 2/2] drm/i915: More use of GT specific print helpers
From: John Harrison Update a bunch of GT related print messages in non-GT files to use the GT specific helpers. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c | 8 +++- drivers/gpu/drm/i915/i915_driver.c| 3 ++- drivers/gpu/drm/i915/i915_perf.c | 8 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c index 0d3b22a743659..453d855dd1de7 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c @@ -68,8 +68,7 @@ static void gsc_work(struct work_struct *work) * A proxy failure right after firmware load means the proxy-init * step has failed so mark GSC as not usable after this */ - drm_err(>i915->drm, - "GSC proxy handler failed to init\n"); + gt_err(gt, "GSC proxy handler failed to init\n"); intel_uc_fw_change_status(>fw, INTEL_UC_FIRMWARE_LOAD_FAIL); } goto out_put; @@ -83,11 +82,10 @@ static void gsc_work(struct work_struct *work) * status register to check if the proxy init was actually successful */ if (intel_gsc_uc_fw_proxy_init_done(gsc, false)) { - drm_dbg(>i915->drm, "GSC Proxy initialized\n"); + gt_dbg(gt, "GSC Proxy initialized\n"); intel_uc_fw_change_status(>fw, INTEL_UC_FIRMWARE_RUNNING); } else { - drm_err(>i915->drm, - "GSC status reports proxy init not complete\n"); + gt_err(gt, "GSC status reports proxy init not complete\n"); intel_uc_fw_change_status(>fw, INTEL_UC_FIRMWARE_LOAD_FAIL); } } diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index e5a94b08d5efe..944ab895da72e 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -71,6 +71,7 @@ #include "gem/i915_gem_pm.h" #include "gt/intel_gt.h" #include "gt/intel_gt_pm.h" +#include "gt/intel_gt_print.h" #include "gt/intel_rc6.h" #include "pxp/intel_pxp.h" @@ -429,7 +430,7 @@ static int i915_pcode_init(struct drm_i915_private *i915) for_each_gt(gt, i915, id) { ret = intel_pcode_init(gt->uncore); if (ret) { - drm_err(>i915->drm, "gt%d: intel_pcode_init failed %d\n", id, ret); + gt_err(gt, "intel_pcode_init failed %d\n", ret); return ret; } } diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 1347e4ec9dd5a..8f7ab64feec0d 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -206,6 +206,7 @@ #include "gt/intel_gt.h" #include "gt/intel_gt_clock_utils.h" #include "gt/intel_gt_mcr.h" +#include "gt/intel_gt_print.h" #include "gt/intel_gt_regs.h" #include "gt/intel_lrc.h" #include "gt/intel_lrc_reg.h" @@ -1659,9 +1660,8 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream) free_noa_wait(stream); if (perf->spurious_report_rs.missed) { - drm_notice(>i915->drm, - "%d spurious OA report notices suppressed due to ratelimiting\n", - perf->spurious_report_rs.missed); + gt_notice(gt, "%d spurious OA report notices suppressed due to ratelimiting\n", + perf->spurious_report_rs.missed); } } @@ -1852,7 +1852,7 @@ static int alloc_oa_buffer(struct i915_perf_stream *stream) */ ret = i915_vma_pin(vma, 0, SZ_16M, PIN_GLOBAL | PIN_HIGH); if (ret) { - drm_err(>i915->drm, "Failed to pin OA buffer %d\n", ret); + gt_err(gt, "Failed to pin OA buffer %d\n", ret); goto err_unref; } -- 2.41.0
[Intel-gfx] [PATCH 1/2] drm/i915/gt: More use of GT specific print helpers
From: John Harrison A bunch of print messages got missed in the update to using sub-system specific helpers. So update those. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 29 + drivers/gpu/drm/i915/gt/intel_gsc.c | 11 drivers/gpu/drm/i915/gt/intel_gt_print.h| 3 +++ drivers/gpu/drm/i915/gt/intel_reset.c | 26 -- drivers/gpu/drm/i915/gt/intel_workarounds.c | 13 - 5 files changed, 39 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index b1a1d07e2e217..179d9546865b0 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -316,10 +316,9 @@ u32 intel_engine_context_size(struct intel_gt *gt, u8 class) * out in the wash. */ cxt_size = intel_uncore_read(uncore, CXT_SIZE) + 1; - drm_dbg(>i915->drm, - "graphics_ver = %d CXT_SIZE = %d bytes [0x%08x]\n", - GRAPHICS_VER(gt->i915), cxt_size * 64, - cxt_size - 1); + gt_dbg(gt, "graphics_ver = %d CXT_SIZE = %d bytes [0x%08x]\n", + GRAPHICS_VER(gt->i915), cxt_size * 64, + cxt_size - 1); return round_up(cxt_size * 64, PAGE_SIZE); case 3: case 2: @@ -788,7 +787,7 @@ static void engine_mask_apply_media_fuses(struct intel_gt *gt) if (!(BIT(i) & vdbox_mask)) { gt->info.engine_mask &= ~BIT(_VCS(i)); - drm_dbg(>drm, "vcs%u fused off\n", i); + gt_dbg(gt, "vcs%u fused off\n", i); continue; } @@ -796,8 +795,7 @@ static void engine_mask_apply_media_fuses(struct intel_gt *gt) gt->info.vdbox_sfc_access |= BIT(i); logical_vdbox++; } - drm_dbg(>drm, "vdbox enable: %04x, instances: %04lx\n", - vdbox_mask, VDBOX_MASK(gt)); + gt_dbg(gt, "vdbox enable: %04x, instances: %04lx\n", vdbox_mask, VDBOX_MASK(gt)); GEM_BUG_ON(vdbox_mask != VDBOX_MASK(gt)); for (i = 0; i < I915_MAX_VECS; i++) { @@ -808,11 +806,10 @@ static void engine_mask_apply_media_fuses(struct intel_gt *gt) if (!(BIT(i) & vebox_mask)) { gt->info.engine_mask &= ~BIT(_VECS(i)); - drm_dbg(>drm, "vecs%u fused off\n", i); + gt_dbg(gt, "vecs%u fused off\n", i); } } - drm_dbg(>drm, "vebox enable: %04x, instances: %04lx\n", - vebox_mask, VEBOX_MASK(gt)); + gt_dbg(gt, "vebox enable: %04x, instances: %04lx\n", vebox_mask, VEBOX_MASK(gt)); GEM_BUG_ON(vebox_mask != VEBOX_MASK(gt)); } @@ -838,7 +835,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt) */ for_each_clear_bit(i, _mask, I915_MAX_CCS) { info->engine_mask &= ~BIT(_CCS(i)); - drm_dbg(>drm, "ccs%u fused off\n", i); + gt_dbg(gt, "ccs%u fused off\n", i); } } @@ -866,8 +863,8 @@ static void engine_mask_apply_copy_fuses(struct intel_gt *gt) _BCS(instance)); if (mask & info->engine_mask) { - drm_dbg(>drm, "bcs%u fused off\n", instance); - drm_dbg(>drm, "bcs%u fused off\n", instance + 1); + gt_dbg(gt, "bcs%u fused off\n", instance); + gt_dbg(gt, "bcs%u fused off\n", instance + 1); info->engine_mask &= ~mask; } @@ -907,8 +904,7 @@ static intel_engine_mask_t init_engine_mask(struct intel_gt *gt) *submission, which will wake up the GSC power well. */ if (__HAS_ENGINE(info->engine_mask, GSC0) && !intel_uc_wants_gsc_uc(>uc)) { - drm_notice(>i915->drm, - "No GSC FW selected, disabling GSC CS and media C6\n"); + gt_notice(gt, "No GSC FW selected, disabling GSC CS and media C6\n"); info->engine_mask &= ~BIT(GSC0); } @@ -1097,8 +1093,7 @@ static int init_status_page(struct intel_engine_cs *engine) */ obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); if (IS_ERR(obj)) { - drm_err(>i915->drm, - "Failed to allocate status page\n"); + gt_err(engine->gt, "Failed to allocate status page\n"); return PTR_ERR(obj); } diff --git a/drivers/gpu/drm/i915/gt/intel_gsc.c b/drivers/gpu/drm/i915/gt/intel_gsc.c index bcc3605158dbd..6d440de8ba017 100644 ---
[Intel-gfx] [PATCH 0/2] More print message helper updates
From: John Harrison There was an update a while back to use sub-system specific print helpers that implicitly add sub-system specific information to the print. It seems a bunch of GT related messages got missed in that update. So update them now. Signed-off-by: John Harrison John Harrison (2): drm/i915/gt: More use of GT specific print helpers drm/i915: More use of GT specific print helpers drivers/gpu/drm/i915/gt/intel_engine_cs.c | 29 + drivers/gpu/drm/i915/gt/intel_gsc.c | 11 drivers/gpu/drm/i915/gt/intel_gt_print.h| 3 +++ drivers/gpu/drm/i915/gt/intel_reset.c | 26 -- drivers/gpu/drm/i915/gt/intel_workarounds.c | 13 - drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c | 8 +++--- drivers/gpu/drm/i915/i915_driver.c | 3 ++- drivers/gpu/drm/i915/i915_perf.c| 8 +++--- 8 files changed, 48 insertions(+), 53 deletions(-) -- 2.41.0
[Intel-gfx] [PATCH] drm/i915/guc: Update 'recommended' version to 70.12.1 for DG2/ADL-S/ADL-P/MTL
From: John Harrison The latest GuC has new features and new workarounds that we wish to enable. So let the universe know that it is useful to update their firmware. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 32e27e9a2490f..362639162ed60 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -88,12 +88,12 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, * security fixes, etc. to be enabled. */ #define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp) \ - fw_def(METEORLAKE, 0, guc_maj(mtl, 70, 6, 6)) \ - fw_def(DG2, 0, guc_maj(dg2, 70, 5, 1)) \ - fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5, 1)) \ + fw_def(METEORLAKE, 0, guc_maj(mtl, 70, 12, 1)) \ + fw_def(DG2, 0, guc_maj(dg2, 70, 12, 1)) \ + fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 12, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 69, 0, 3)) \ - fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5, 1)) \ + fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 12, 1)) \ fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 70, 1, 1)) \ fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 69, 0, 3)) \ fw_def(DG1, 0, guc_maj(dg1, 70, 5, 1)) \ -- 2.41.0
[Intel-gfx] [CI] PR for new GuC v70.12.1
The following changes since commit 5105ff4b9f43ba08d0a22260d670120e53c4b667: Merge branch 'mlimonci/upstream-packaging' into 'main' (2023-10-04 12:35:17 +) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm-firmware guc_70.12.1 for you to fetch changes up to 22fb3576f39769162c5da556159b72745b8570a8: i915: Add GuC v70.12.1 for DG2, TGL, ADL-P and MTL (2023-10-06 01:52:14 -0700) John Harrison (1): i915: Add GuC v70.12.1 for DG2, TGL, ADL-P and MTL WHENCE | 8 i915/adlp_guc_70.bin | Bin 297984 -> 342528 bytes i915/dg2_guc_70.bin | Bin 385856 -> 443200 bytes i915/mtl_guc_70.bin | Bin 308032 -> 365376 bytes i915/tgl_guc_70.bin | Bin 285888 -> 329984 bytes 5 files changed, 4 insertions(+), 4 deletions(-)
[Intel-gfx] [PATCH] drm/i915/guc: Enable WA 14018913170
From: Daniele Ceraolo Spurio The GuC handles the WA, the KMD just needs to set the flag to enable it on the appropriate platforms. Signed-off-by: John Harrison Signed-off-by: Daniele Ceraolo Spurio Reviewed-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 1 + 3 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 27df41c53b890..3f3df1166b860 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -319,6 +319,12 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) if (!RCS_MASK(gt)) flags |= GUC_WA_RCS_REGS_IN_CCS_REGS_LIST; + /* Wa_14018913170 */ + if (GUC_FIRMWARE_VER(guc) >= MAKE_GUC_VER(70, 7, 0)) { + if (IS_DG2(gt->i915) || IS_METEORLAKE(gt->i915) || IS_PONTEVECCHIO(gt->i915)) + flags |= GUC_WA_ENABLE_TSC_CHECK_ON_RC6; + } + return flags; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 6c392bad29c19..818c8c146fd47 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -295,6 +295,7 @@ struct intel_guc { #define MAKE_GUC_VER(maj, min, pat)(((maj) << 16) | ((min) << 8) | (pat)) #define MAKE_GUC_VER_STRUCT(ver) MAKE_GUC_VER((ver).major, (ver).minor, (ver).patch) #define GUC_SUBMIT_VER(guc) MAKE_GUC_VER_STRUCT((guc)->submission_version) +#define GUC_FIRMWARE_VER(guc) MAKE_GUC_VER_STRUCT((guc)->fw.file_selected.ver) static inline struct intel_guc *log_to_guc(struct intel_guc_log *log) { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index b4d56eccfb1f0..123ad75d2eb28 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -100,6 +100,7 @@ #define GUC_WA_HOLD_CCS_SWITCHOUTBIT(17) #define GUC_WA_POLLCSBIT(18) #define GUC_WA_RCS_REGS_IN_CCS_REGS_LIST BIT(21) +#define GUC_WA_ENABLE_TSC_CHECK_ON_RC6 BIT(22) #define GUC_CTL_FEATURE2 #define GUC_CTL_ENABLE_SLPC BIT(2) -- 2.41.0
[Intel-gfx] [PATCH 3/3] drm/i915/mtl: Add counters for engine busyness ticks
From: Umesh Nerlige Ramappa In new version of GuC engine busyness, GuC provides engine busyness ticks as a 64 bit counter. Add a new counter to relay this value to the user as is. Signed-off-by: Umesh Nerlige Ramappa Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/intel_engine.h| 1 + drivers/gpu/drm/i915/gt/intel_engine_cs.c | 16 + drivers/gpu/drm/i915/gt/intel_engine_types.h | 12 drivers/gpu/drm/i915/gt/intel_engine_user.c | 1 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 67 ++- drivers/gpu/drm/i915/i915_pmu.c | 25 ++- drivers/gpu/drm/i915/i915_pmu.h | 2 +- include/uapi/drm/i915_drm.h | 13 +++- 8 files changed, 116 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index b58c30ac8ef02..57af7ec8ecd82 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -249,6 +249,7 @@ void intel_engine_dump_active_requests(struct list_head *requests, ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine, ktime_t *now); +u64 intel_engine_get_busy_ticks(struct intel_engine_cs *engine); void intel_engine_get_hung_entity(struct intel_engine_cs *engine, struct intel_context **ce, struct i915_request **rq); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 84a75c95f3f7d..1c9ffb1ae9889 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -2426,6 +2426,22 @@ ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine, ktime_t *now) return engine->busyness(engine, now); } +/** + * intel_engine_get_busy_ticks() - Return current accumulated engine busyness + * ticks + * @engine: engine to report on + * + * Returns accumulated ticks @engine was busy since engine stats were enabled. + */ +u64 intel_engine_get_busy_ticks(struct intel_engine_cs *engine) +{ + if (!engine->busyness_ticks || + !(engine->flags & I915_ENGINE_SUPPORTS_TICKS_STATS)) + return 0; + + return engine->busyness_ticks(engine); +} + struct intel_context * intel_engine_create_virtual(struct intel_engine_cs **siblings, unsigned int count, unsigned long flags) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 40fd8f984d64b..a88d40c74d604 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -548,6 +548,11 @@ struct intel_engine_cs { ktime_t (*busyness)(struct intel_engine_cs *engine, ktime_t *now); + /* +* Get engine busyness ticks +*/ + u64 (*busyness_ticks)(struct intel_engine_cs *engine); + struct intel_engine_execlists execlists; /* @@ -574,6 +579,7 @@ struct intel_engine_cs { #define I915_ENGINE_HAS_EU_PRIORITYBIT(10) #define I915_ENGINE_FIRST_RENDER_COMPUTE BIT(11) #define I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT BIT(12) +#define I915_ENGINE_SUPPORTS_TICKS_STATS BIT(13) unsigned int flags; /* @@ -649,6 +655,12 @@ intel_engine_supports_stats(const struct intel_engine_cs *engine) return engine->flags & I915_ENGINE_SUPPORTS_STATS; } +static inline bool +intel_engine_supports_tick_stats(const struct intel_engine_cs *engine) +{ + return engine->flags & I915_ENGINE_SUPPORTS_TICKS_STATS; +} + static inline bool intel_engine_has_preemption(const struct intel_engine_cs *engine) { diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c index dcedff41a825f..69eb610b5ab0a 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_user.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c @@ -100,6 +100,7 @@ static void set_scheduler_caps(struct drm_i915_private *i915) MAP(HAS_PREEMPTION, PREEMPTION), MAP(HAS_SEMAPHORES, SEMAPHORES), MAP(SUPPORTS_STATS, ENGINE_BUSY_STATS), + MAP(SUPPORTS_TICKS_STATS, ENGINE_BUSY_TICKS_STATS), #undef MAP }; struct intel_engine_cs *engine; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 0c1fee5360777..71749fb9ad35b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1289,12 +1289,7 @@ static void busy_v1_guc_update_pm_timestamp(struct intel_guc *guc, ktime_t *now) guc->busy.v1.gt_stamp = ((u64)gt_stamp_hi << 32) | gt_stamp_lo; } -/* - * Unlike the execlist mode of submission total and active times are in terms of - * gt clocks. The *now parameter is retained to return the cpu time at which
[Intel-gfx] [PATCH 1/3] drm/i915/guc: Support new and improved engine busyness
From: John Harrison The GuC has been extended to support a much more friendly engine busyness interface. So partition the old interface into a 'busy_v1' space and add 'busy_v2' support alongside. And if v2 is available, use that in preference to v1. Note that v2 provides extra features over and above v1 which will be exposed via PMU in subsequent patches. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/intel_engine_types.h | 4 +- .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 4 +- drivers/gpu/drm/i915/gt/uc/intel_guc.h| 82 ++-- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 55 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h| 9 +- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 23 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 381 ++ 7 files changed, 427 insertions(+), 131 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index a7e6775980043..40fd8f984d64b 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -323,7 +323,7 @@ struct intel_engine_execlists_stats { ktime_t start; }; -struct intel_engine_guc_stats { +struct intel_engine_guc_stats_v1 { /** * @running: Active state of the engine when busyness was last sampled. */ @@ -603,7 +603,7 @@ struct intel_engine_cs { struct { union { struct intel_engine_execlists_stats execlists; - struct intel_engine_guc_stats guc; + struct intel_engine_guc_stats_v1 guc_v1; }; /** diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h index f359bef046e0b..c190a99a36c38 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h @@ -137,7 +137,9 @@ enum intel_guc_action { INTEL_GUC_ACTION_DEREGISTER_CONTEXT_DONE = 0x4600, INTEL_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC = 0x4601, INTEL_GUC_ACTION_CLIENT_SOFT_RESET = 0x5507, - INTEL_GUC_ACTION_SET_ENG_UTIL_BUFF = 0x550A, + INTEL_GUC_ACTION_SET_ENG_UTIL_BUFF_V1 = 0x550A, + INTEL_GUC_ACTION_SET_DEVICE_ENGINE_UTILIZATION_V2 = 0x550C, + INTEL_GUC_ACTION_SET_FUNCTION_ENGINE_UTILIZATION_V2 = 0x550D, INTEL_GUC_ACTION_STATE_CAPTURE_NOTIFICATION = 0x8002, INTEL_GUC_ACTION_NOTIFY_FLUSH_LOG_BUFFER_TO_FILE = 0x8003, INTEL_GUC_ACTION_NOTIFY_CRASH_DUMP_POSTED = 0x8004, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 6c392bad29c19..e6502ab5f049f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -226,45 +226,61 @@ struct intel_guc { struct mutex send_mutex; /** -* @timestamp: GT timestamp object that stores a copy of the timestamp -* and adjusts it for overflow using a worker. +* @busy: Data used by the different versions of engine busyness implementations. */ - struct { - /** -* @lock: Lock protecting the below fields and the engine stats. -*/ - spinlock_t lock; - - /** -* @gt_stamp: 64 bit extended value of the GT timestamp. -*/ - u64 gt_stamp; - - /** -* @ping_delay: Period for polling the GT timestamp for -* overflow. -*/ - unsigned long ping_delay; - - /** -* @work: Periodic work to adjust GT timestamp, engine and -* context usage for overflows. -*/ - struct delayed_work work; - + union { /** -* @shift: Right shift value for the gpm timestamp +* @v1: Data used by v1 engine busyness implementation. Mostly a copy +* of the GT timestamp extended to 64 bits and the worker for maintaining it. */ - u32 shift; + struct { + /** +* @lock: Lock protecting the below fields and the engine stats. +*/ + spinlock_t lock; + + /** +* @gt_stamp: 64 bit extended value of the GT timestamp. +*/ + u64 gt_stamp; + + /** +* @ping_delay: Period for polling the GT timestamp for +* overflow. +*/ + unsigned long ping_delay; + + /** +* @work: Periodic work to adjust GT timestamp, engine and +* context usage for overflows. +
[Intel-gfx] [PATCH 0/3] Engine busyness v2
From: John Harrison The latest GuC implements a new and improved scheme for tracking engine busyness. So make use of it. Note that this change comes along with a new set of PMU counters. The old counters have a fundamental problem that they are defined in terms of wall time but the sampling is now all done by the GPU in terms of clock ticks. This leads to issues with timebase conversion, some of which are non-trivial. For existing platforms, the old counters will still be updated by the new scheme and will still suffer all the same issues. For newer platforms (MTL onwards), the old counters are no longer supported. Instead, there is a new set of tick based counters. These include the actual busyness count per engine plus a total ticks count. The intention is that they should be queried as an atomic pair and used together to determine a busyness percentage. No assumptions may be made about tick frequencies or relations to wall time. Test-with: 20230922215233.2438200-1-umesh.nerlige.rama...@intel.com Signed-off-by: John Harrison John Harrison (1): drm/i915/guc: Support new and improved engine busyness Umesh Nerlige Ramappa (2): drm/i915/mtl: Add a PMU counter for total active ticks drm/i915/mtl: Add counters for engine busyness ticks drivers/gpu/drm/i915/gt/intel_engine.h| 1 + drivers/gpu/drm/i915/gt/intel_engine_cs.c | 16 + drivers/gpu/drm/i915/gt/intel_engine_types.h | 16 +- drivers/gpu/drm/i915/gt/intel_engine_user.c | 1 + .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 4 +- drivers/gpu/drm/i915/gt/uc/intel_guc.h| 82 ++-- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 55 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h| 9 +- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 23 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 460 ++ .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 1 + drivers/gpu/drm/i915/i915_pmu.c | 31 +- drivers/gpu/drm/i915/i915_pmu.h | 2 +- include/uapi/drm/i915_drm.h | 15 +- 14 files changed, 570 insertions(+), 146 deletions(-) -- 2.41.0
[Intel-gfx] [PATCH 2/3] drm/i915/mtl: Add a PMU counter for total active ticks
From: Umesh Nerlige Ramappa Current engine busyness interface exposed by GuC has a few issues: - The busyness of active engine is calculated using 2 values provided by GuC and is prone to race between CPU reading those values and GuC updating them. Any sort of HW synchronization would be at the cost of scheduling latencies. - GuC provides only 32 bit values for busyness and KMD has to run a worker to extend the values to 64 bit. In addition KMD also needs to extend the GT timestamp to 64 bits so that it can be used to calculate active busyness for an engine. To address these issues, GuC provides a new interface to calculate engine busyness. GuC accumulates the busyness ticks in a 64 bit value and also internally updates the busyness for an active context using a periodic timer. This simplifies the KMD implementation such that KMD only needs to relay the busyness value to the user. In addition to fixing the interface, GuC also provides a periodically total active ticks that the GT has been running for. This counter is exposed to the user so that the % busyness can be calculated as follows: busyness % = (engine active ticks/total active ticks) * 100. Implement the new interface and start by adding a new counter for total active ticks. Signed-off-by: Umesh Nerlige Ramappa Signed-off-by: John Harrison --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 24 +++ .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 1 + drivers/gpu/drm/i915/i915_pmu.c | 6 + include/uapi/drm/i915_drm.h | 2 ++ 4 files changed, 33 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 88465d701c278..0c1fee5360777 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1607,6 +1607,30 @@ static ktime_t busy_v2_guc_engine_busyness(struct intel_engine_cs *engine, ktime return ns_to_ktime(total); } +static u64 busy_v1_intel_guc_total_active_ticks(struct intel_guc *guc) +{ + return guc->busy.v1.gt_stamp; +} + +static u64 busy_v2_intel_guc_total_active_ticks(struct intel_guc *guc) +{ + u64 ticks_gt; + + __busy_v2_get_engine_usage_record(guc, NULL, NULL, NULL, _gt); + + return ticks_gt; +} + +u64 intel_guc_total_active_ticks(struct intel_gt *gt) +{ + struct intel_guc *guc = >uc.guc; + + if (GUC_SUBMIT_VER(guc) < MAKE_GUC_VER(1, 3, 1)) + return busy_v1_intel_guc_total_active_ticks(guc); + else + return busy_v2_intel_guc_total_active_ticks(guc); +} + static int busy_v2_guc_action_enable_usage_stats_device(struct intel_guc *guc) { u32 offset = guc_engine_usage_offset_v2_device(guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h index c57b29cdb1a64..f6d42838825f2 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h @@ -30,6 +30,7 @@ void intel_guc_dump_active_requests(struct intel_engine_cs *engine, struct drm_printer *m); void intel_guc_busyness_park(struct intel_gt *gt); void intel_guc_busyness_unpark(struct intel_gt *gt); +u64 intel_guc_total_active_ticks(struct intel_gt *gt); bool intel_guc_virtual_engine_has_heartbeat(const struct intel_engine_cs *ve); diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index d35973b411863..4f52636eb4a80 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -563,6 +563,8 @@ config_status(struct drm_i915_private *i915, u64 config) break; case I915_PMU_SOFTWARE_GT_AWAKE_TIME: break; + case I915_PMU_TOTAL_ACTIVE_TICKS: + break; default: return -ENOENT; } @@ -678,6 +680,9 @@ static u64 __i915_pmu_event_read(struct perf_event *event) case I915_PMU_SOFTWARE_GT_AWAKE_TIME: val = ktime_to_ns(intel_gt_get_awake_time(to_gt(i915))); break; + case I915_PMU_TOTAL_ACTIVE_TICKS: + val = intel_guc_total_active_ticks(i915->gt[gt_id]); + break; } } @@ -986,6 +991,7 @@ create_event_attributes(struct i915_pmu *pmu) __global_event(2, "interrupts", NULL), __event(3, "rc6-residency", "ns"), __event(4, "software-gt-awake-time", "ns"), + __event(5, "total-active-ticks", NULL), }; static const struct { enum drm_i915_pmu_engine_sample sample; diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 7000e5910a1d7..e26dd27ff4a5f 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -296,6 +296,7 @@ enum
[Intel-gfx] [PATCH] drm/i915/guc: Suppress 'ignoring reset notification' message
From: John Harrison If an active context has been banned (e.g. Ctrl+C killed) then it is likely to be reset as part of evicting it from the hardware. That results in a 'ignoring context reset notification: banned = 1' message at info level. This confuses/concerns people and makes them thing something has gone wrong when it hasn't. There is already a debug level message with essentially the same information. So drop the 'ignore' info level one and just add the 'ignore' flag to the debug level one instead (which will therefore not appear by default but will still show up in CI runs). Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index cabdc645fcddb..da7331346df1f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4770,19 +4770,19 @@ static void guc_context_replay(struct intel_context *ce) static void guc_handle_context_reset(struct intel_guc *guc, struct intel_context *ce) { + bool capture = intel_context_is_schedulable(ce); + trace_intel_context_reset(ce); - guc_dbg(guc, "Got context reset notification: 0x%04X on %s, exiting = %s, banned = %s\n", + guc_dbg(guc, "%s context reset notification: 0x%04X on %s, exiting = %s, banned = %s\n", + capture ? "Got" : "Ignoring", ce->guc_id.id, ce->engine->name, str_yes_no(intel_context_is_exiting(ce)), str_yes_no(intel_context_is_banned(ce))); - if (likely(intel_context_is_schedulable(ce))) { + if (capture) { capture_error_state(guc, ce); guc_context_replay(ce); - } else { - guc_info(guc, "Ignoring context reset notification of exiting context 0x%04X on %s", -ce->guc_id.id, ce->engine->name); } } -- 2.41.0
[Intel-gfx] [PATCH 3/4] drm/i915/guc: Add support for w/a KLVs
From: John Harrison To prevent running out of bits, new w/a enable flags are being added via a KLV system instead of a 32 bit flags word. Signed-off-by: John Harrison --- .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc.h| 3 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 64 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 5 +- 5 files changed, 77 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h index dabeaf4f245f3..00d6402333f8e 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h @@ -36,6 +36,7 @@ enum intel_guc_load_status { INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_START, INTEL_GUC_LOAD_STATUS_MPU_DATA_INVALID = 0x73, INTEL_GUC_LOAD_STATUS_INIT_MMIO_SAVE_RESTORE_INVALID = 0x74, + INTEL_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR= 0x75, INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_END, INTEL_GUC_LOAD_STATUS_READY= 0xF0, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 6c392bad29c19..3b1fc5f96306b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -186,6 +186,8 @@ struct intel_guc { struct guc_mmio_reg *ads_regset; /** @ads_golden_ctxt_size: size of the golden contexts in the ADS */ u32 ads_golden_ctxt_size; + /** @ads_waklv_size: size of workaround KLVs */ + u32 ads_waklv_size; /** @ads_capture_size: size of register lists in the ADS used for error capture */ u32 ads_capture_size; /** @ads_engine_usage_size: size of engine usage in the ADS */ @@ -295,6 +297,7 @@ struct intel_guc { #define MAKE_GUC_VER(maj, min, pat)(((maj) << 16) | ((min) << 8) | (pat)) #define MAKE_GUC_VER_STRUCT(ver) MAKE_GUC_VER((ver).major, (ver).minor, (ver).patch) #define GUC_SUBMIT_VER(guc) MAKE_GUC_VER_STRUCT((guc)->submission_version) +#define GUC_FIRMWARE_VER(guc) MAKE_GUC_VER_STRUCT((guc)->fw.file_selected.ver) static inline struct intel_guc *log_to_guc(struct intel_guc_log *log) { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 63724e17829a7..792910af3a481 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -46,6 +46,10 @@ * +---+ * | padding | * +---+ <== 4K aligned + * | w/a KLVs | + * +---+ + * | padding | + * +---+ <== 4K aligned * | capture lists | * +---+ * | padding | @@ -88,6 +92,11 @@ static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc) return PAGE_ALIGN(guc->ads_golden_ctxt_size); } +static u32 guc_ads_waklv_size(struct intel_guc *guc) +{ + return PAGE_ALIGN(guc->ads_waklv_size); +} + static u32 guc_ads_capture_size(struct intel_guc *guc) { return PAGE_ALIGN(guc->ads_capture_size); @@ -113,7 +122,7 @@ static u32 guc_ads_golden_ctxt_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } -static u32 guc_ads_capture_offset(struct intel_guc *guc) +static u32 guc_ads_waklv_offset(struct intel_guc *guc) { u32 offset; @@ -123,6 +132,16 @@ static u32 guc_ads_capture_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } +static u32 guc_ads_capture_offset(struct intel_guc *guc) +{ + u32 offset; + + offset = guc_ads_waklv_offset(guc) + +guc_ads_waklv_size(guc); + + return PAGE_ALIGN(offset); +} + static u32 guc_ads_private_data_offset(struct intel_guc *guc) { u32 offset; @@ -791,6 +810,40 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } +static void guc_waklv_init(struct intel_guc *guc) +{ + struct intel_gt *gt = guc_to_gt(guc); + u32 offset, addr_ggtt, remain, size; + + if (!intel_uc_uses_guc_submission(>uc)) + return; + + if (GUC_FIRMWARE_VER(guc) < MAKE_GUC_VER(70, 10, 0)) + return; + + GEM_BUG_ON(iosys_map_is_null(>ads_map)); + offset = guc_ads_waklv_offset(guc); + remain = guc_ads_waklv_size(guc); + + /* Add workarounds here */ + + size = guc_ads_waklv_size(guc) - remain; + if (!size) + return; + + addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; + +
[Intel-gfx] [PATCH 4/4] drm/i915/guc: Enable Wa_14019159160
From: John Harrison Use the new w/a KLV support to enable a MTL w/a. Note, this w/a is a super-set of Wa_16019325821, so requires turning that one as well as setting the new flag for Wa_14019159160 itself. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 3 +++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 1 + drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 7 + drivers/gpu/drm/i915/gt/uc/intel_guc.c| 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 26 ++- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 1 + 6 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index 8b494825c55f2..d31c405b095b7 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -734,6 +734,7 @@ static u32 *gen12_emit_preempt_busywait(struct i915_request *rq, u32 *cs) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ #define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET 0x540 static u32 hold_switchout_semaphore_offset(struct i915_request *rq) { @@ -743,6 +744,7 @@ static u32 hold_switchout_semaphore_offset(struct i915_request *rq) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ static u32 *hold_switchout_emit_wa_busywait(struct i915_request *rq, u32 *cs) { int i; @@ -783,6 +785,7 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ + /* Wa_14019159160 */ if (intel_engine_uses_wa_hold_switchout(rq->engine)) cs = hold_switchout_emit_wa_busywait(rq, cs); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 68fe1cef9cd94..9b3051600856e 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -684,6 +684,7 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) /* Wa_14014475959:dg2 */ /* Wa_16019325821 */ +/* Wa_14019159160 */ static inline bool intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine) { diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h index 58012edd4eb0e..bebf28e3c4794 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h @@ -101,4 +101,11 @@ enum { GUC_CONTEXT_POLICIES_KLV_NUM_IDS = 5, }; +/* + * Workaround keys: + */ +enum { + GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE = 0x9001, +}; + #endif /* _ABI_GUC_KLVS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 4001679ba0793..e74590a71d113 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -295,6 +295,7 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) flags |= GUC_WA_HOLD_CCS_SWITCHOUT; /* Wa_16019325821 */ + /* Wa_14019159160 */ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) flags |= GUC_WA_RCS_CCS_SWITCHOUT; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 792910af3a481..a9fd2e96f27f5 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -810,6 +810,25 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } +/* Wa_14019159160 */ +static u32 guc_waklv_ra_mode(struct intel_guc *guc, u32 offset, u32 remain) +{ + u32 size; + u32 klv_entry[] = { + /* 16:16 key/length */ + FIELD_PREP(GUC_KLV_0_KEY, GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE) | + FIELD_PREP(GUC_KLV_0_LEN, 0), + /* 0 dwords data */ + }; + + size = sizeof(klv_entry); + GEM_BUG_ON(remain < size); + + iosys_map_memcpy_to(>ads_map, offset, klv_entry, size); + + return size; +} + static void guc_waklv_init(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -825,7 +844,12 @@ static void guc_waklv_init(struct intel_guc *guc) offset = guc_ads_waklv_offset(guc); remain = guc_ads_waklv_size(guc); - /* Add workarounds here */ + /* Wa_14019159160 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { + size = guc_waklv_ra_mode(guc, offset, remain); + offset += size; + remain -= size; + } size = guc_ads_waklv_size(guc) - remain; if (!size) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index ff38a815701ce..c8428e4b03592 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++
[Intel-gfx] [PATCH 2/4] drm/i915: Enable Wa_16019325821
From: John Harrison Some platforms require holding RCS context switches until CCS is idle (the reverse w/a of Wa_14014475959). Some platforms require both versions. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 19 +++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 7 --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 4 drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 3 ++- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 8 +++- 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index 0143445dba830..8b494825c55f2 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -733,21 +733,23 @@ static u32 *gen12_emit_preempt_busywait(struct i915_request *rq, u32 *cs) } /* Wa_14014475959:dg2 */ -#define CCS_SEMAPHORE_PPHWSP_OFFSET0x540 -static u32 ccs_semaphore_offset(struct i915_request *rq) +/* Wa_16019325821 */ +#define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET 0x540 +static u32 hold_switchout_semaphore_offset(struct i915_request *rq) { return i915_ggtt_offset(rq->context->state) + - (LRC_PPHWSP_PN * PAGE_SIZE) + CCS_SEMAPHORE_PPHWSP_OFFSET; + (LRC_PPHWSP_PN * PAGE_SIZE) + HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET; } /* Wa_14014475959:dg2 */ -static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) +/* Wa_16019325821 */ +static u32 *hold_switchout_emit_wa_busywait(struct i915_request *rq, u32 *cs) { int i; *cs++ = MI_ATOMIC_INLINE | MI_ATOMIC_GLOBAL_GTT | MI_ATOMIC_CS_STALL | MI_ATOMIC_MOVE; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; *cs++ = 1; @@ -763,7 +765,7 @@ static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) MI_SEMAPHORE_POLL | MI_SEMAPHORE_SAD_EQ_SDD; *cs++ = 0; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; return cs; @@ -780,8 +782,9 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs) cs = gen12_emit_preempt_busywait(rq, cs); /* Wa_14014475959:dg2 */ - if (intel_engine_uses_wa_hold_ccs_switchout(rq->engine)) - cs = ccs_emit_wa_busywait(rq, cs); + /* Wa_16019325821 */ + if (intel_engine_uses_wa_hold_switchout(rq->engine)) + cs = hold_switchout_emit_wa_busywait(rq, cs); rq->tail = intel_ring_offset(rq, cs); assert_ring_tail_valid(rq->ring, rq->tail); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index a7e6775980043..68fe1cef9cd94 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -573,7 +573,7 @@ struct intel_engine_cs { #define I915_ENGINE_HAS_RCS_REG_STATE BIT(9) #define I915_ENGINE_HAS_EU_PRIORITYBIT(10) #define I915_ENGINE_FIRST_RENDER_COMPUTE BIT(11) -#define I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT BIT(12) +#define I915_ENGINE_USES_WA_HOLD_SWITCHOUT BIT(12) unsigned int flags; /* @@ -683,10 +683,11 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) } /* Wa_14014475959:dg2 */ +/* Wa_16019325821 */ static inline bool -intel_engine_uses_wa_hold_ccs_switchout(struct intel_engine_cs *engine) +intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine) { - return engine->flags & I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT; + return engine->flags & I915_ENGINE_USES_WA_HOLD_SWITCHOUT; } #endif /* __INTEL_ENGINE_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 27df41c53b890..4001679ba0793 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -294,6 +294,10 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) IS_DG2(gt->i915)) flags |= GUC_WA_HOLD_CCS_SWITCHOUT; + /* Wa_16019325821 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) + flags |= GUC_WA_RCS_CCS_SWITCHOUT; + /* * Wa_14012197797 * Wa_22011391025 diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index b4d56eccfb1f0..f97af0168a66b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -95,8 +95,9 @@ #define GUC_WA_GAM_CREDITS BIT(10) #define GUC_WA_DUAL_QUEUEBIT(11) #define GUC_WA_RCS_RESET_BEFORE_RC6 BIT(13) -#define GUC_WA_CONTEXT_ISOLATION BIT(15) #define GUC_WA_PRE_PARSERBIT(14) +#define GUC_WA_CONTEXT_ISOLATION BIT(15) +#define GUC_WA_RCS_CCS_SWITCHOUT
[Intel-gfx] [PATCH 1/4] drm/i915/guc: Update 'recommended' version to 70.11.0 for DG2/ADL-P/MTL
From: John Harrison The latest GuC has new features and new workarounds that we wish to enable. So let the universe know that it is useful to update their firmware. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 32e27e9a2490f..a40f96c98308b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -88,9 +88,9 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, * security fixes, etc. to be enabled. */ #define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp) \ - fw_def(METEORLAKE, 0, guc_maj(mtl, 70, 6, 6)) \ - fw_def(DG2, 0, guc_maj(dg2, 70, 5, 1)) \ - fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5, 1)) \ + fw_def(METEORLAKE, 0, guc_maj(mtl, 70, 11, 0)) \ + fw_def(DG2, 0, guc_maj(dg2, 70, 11, 0)) \ + fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 11, 0)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 69, 0, 3)) \ fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5, 1)) \ -- 2.41.0
[Intel-gfx] [PATCH 0/4] Enable Wa_14019159160 and Wa_16019325821 for MTL
From: John Harrison Enable Wa_14019159160 and Wa_16019325821 for MTL RCS/CCS workarounds for MTL. Signed-off-by: John Harrison John Harrison (4): drm/i915/guc: Update 'recommended' version to 70.11.0 for DG2/ADL-P/MTL drm/i915: Enable Wa_16019325821 drm/i915/guc: Add support for w/a KLVs drm/i915/guc: Enable Wa_14019159160 drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 22 +++-- drivers/gpu/drm/i915/gt/intel_engine_types.h | 8 +- .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h | 7 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.c| 5 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.h| 3 + drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 88 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 8 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 9 +- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 6 +- 11 files changed, 145 insertions(+), 18 deletions(-) -- 2.41.0
[Intel-gfx] [PATCH 0/2] Enable Wa_14018913170 on DG2/MTL/PVD
From: John Harrison Enable a WA on the latest platforms. Also update the recommended GuC version for those platforms to the latest available. Further patches will follow to make use of other features in the latest GuC firmware, but the w/a at least requires something newer than what was previously in use. Signed-off-by: John Harrison Daniele Ceraolo Spurio (1): drm/i915/guc: Enable WA 14018913170 John Harrison (1): drm/i915/guc: Update 'recommended' version to 70.11.0 for DG2/ADL-P/MTL drivers/gpu/drm/i915/gt/uc/intel_guc.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c| 6 +++--- 4 files changed, 11 insertions(+), 3 deletions(-) -- 2.41.0
[Intel-gfx] [PATCH 2/2] drm/i915/guc: Enable WA 14018913170
From: Daniele Ceraolo Spurio The GuC handles the WA, the KMD just needs to set the flag to enable it on the appropriate platforms. Signed-off-by: John Harrison Signed-off-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 6 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 1 + 3 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 27df41c53b890..3f3df1166b860 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -319,6 +319,12 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) if (!RCS_MASK(gt)) flags |= GUC_WA_RCS_REGS_IN_CCS_REGS_LIST; + /* Wa_14018913170 */ + if (GUC_FIRMWARE_VER(guc) >= MAKE_GUC_VER(70, 7, 0)) { + if (IS_DG2(gt->i915) || IS_METEORLAKE(gt->i915) || IS_PONTEVECCHIO(gt->i915)) + flags |= GUC_WA_ENABLE_TSC_CHECK_ON_RC6; + } + return flags; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 6c392bad29c19..818c8c146fd47 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -295,6 +295,7 @@ struct intel_guc { #define MAKE_GUC_VER(maj, min, pat)(((maj) << 16) | ((min) << 8) | (pat)) #define MAKE_GUC_VER_STRUCT(ver) MAKE_GUC_VER((ver).major, (ver).minor, (ver).patch) #define GUC_SUBMIT_VER(guc) MAKE_GUC_VER_STRUCT((guc)->submission_version) +#define GUC_FIRMWARE_VER(guc) MAKE_GUC_VER_STRUCT((guc)->fw.file_selected.ver) static inline struct intel_guc *log_to_guc(struct intel_guc_log *log) { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index b4d56eccfb1f0..123ad75d2eb28 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -100,6 +100,7 @@ #define GUC_WA_HOLD_CCS_SWITCHOUTBIT(17) #define GUC_WA_POLLCSBIT(18) #define GUC_WA_RCS_REGS_IN_CCS_REGS_LIST BIT(21) +#define GUC_WA_ENABLE_TSC_CHECK_ON_RC6 BIT(22) #define GUC_CTL_FEATURE2 #define GUC_CTL_ENABLE_SLPC BIT(2) -- 2.41.0
[Intel-gfx] [PATCH 1/2] drm/i915/guc: Update 'recommended' version to 70.11.0 for DG2/ADL-P/MTL
From: John Harrison The latest GuC has new features and new workarounds that we wish to enable. So let the universe know that it is useful to update their firmware. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 32e27e9a2490f..a40f96c98308b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -88,9 +88,9 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, * security fixes, etc. to be enabled. */ #define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp) \ - fw_def(METEORLAKE, 0, guc_maj(mtl, 70, 6, 6)) \ - fw_def(DG2, 0, guc_maj(dg2, 70, 5, 1)) \ - fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5, 1)) \ + fw_def(METEORLAKE, 0, guc_maj(mtl, 70, 11, 0)) \ + fw_def(DG2, 0, guc_maj(dg2, 70, 11, 0)) \ + fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 11, 0)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 69, 0, 3)) \ fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5, 1)) \ -- 2.41.0
[Intel-gfx] [CI] PR for new GuC v70.11.0
The following changes since commit dfa11466cf000120d1551146fd5bf78c44941eda: Merge branch 'main' into 'main' (2023-09-07 11:36:57 +) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm-firmware guc_70.11.0 for you to fetch changes up to af0fdbdde5b3e2318aefa4db00115c808a9cfe2d: i915: Add GuC v70.11.0 for DG2, ADL-P and MTL (2023-09-14 14:25:18 -0700) John Harrison (1): i915: Add GuC v70.11.0 for DG2, ADL-P and MTL WHENCE | 6 +++--- i915/adlp_guc_70.bin | Bin 297984 -> 341696 bytes i915/dg2_guc_70.bin | Bin 385856 -> 443200 bytes i915/mtl_guc_70.bin | Bin 308032 -> 365376 bytes 4 files changed, 3 insertions(+), 3 deletions(-)
[Intel-gfx] [PATCH v2] drm/i915/guc: Force a reset on internal GuC error
From: John Harrison If GuC hits an internal error (and survives long enough to report it to the KMD), it is basically toast and will stop until a GT reset and subsequent GuC reload is performed. Previously, the KMD just printed an error message and then waited for the heartbeat to eventually kick in and trigger a reset (assuming the heartbeat had not been disabled). Instead, force the reset immediately to guarantee that it happens and to eliminate the very long heartbeat delay. The captured error state is also more likely to be useful if captured at the time of the error rather than many seconds later. Note that it is not possible to trigger a reset from with the G2H handler itself. The reset prepare process involves flushing outstanding G2H contents. So a deadlock could result. Instead, the G2H handler queues a worker thread to do the reset asynchronously. v2: Flush the worker on suspend and shutdown. Add rate limiting to prevent spam from a totally dead system (review feedback from Daniele). Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 38 +++ drivers/gpu/drm/i915/gt/uc/intel_guc.h| 15 + drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 6 +--- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 569b5fe94c416..12a817b762334 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -159,6 +159,21 @@ static void gen11_disable_guc_interrupts(struct intel_guc *guc) gen11_reset_guc_interrupts(guc); } +static void guc_dead_worker_func(struct work_struct *w) +{ + struct intel_guc *guc = container_of(w, struct intel_guc, dead_guc_worker); + struct intel_gt *gt = guc_to_gt(guc); + unsigned long last = guc->last_dead_guc_jiffies; + unsigned long delta = jiffies_to_msecs(jiffies - last); + + if (delta < 500) { + intel_gt_set_wedged(gt); + } else { + intel_gt_handle_error(gt, ALL_ENGINES, I915_ERROR_CAPTURE, "dead GuC"); + guc->last_dead_guc_jiffies = jiffies; + } +} + void intel_guc_init_early(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -171,6 +186,8 @@ void intel_guc_init_early(struct intel_guc *guc) intel_guc_slpc_init_early(>slpc); intel_guc_rc_init_early(guc); + INIT_WORK(>dead_guc_worker, guc_dead_worker_func); + mutex_init(>send_mutex); spin_lock_init(>irq_lock); if (GRAPHICS_VER(i915) >= 11) { @@ -461,6 +478,8 @@ void intel_guc_fini(struct intel_guc *guc) if (!intel_uc_fw_is_loadable(>fw)) return; + flush_work(>dead_guc_worker); + if (intel_guc_slpc_is_used(guc)) intel_guc_slpc_fini(>slpc); @@ -585,6 +604,20 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *request, u32 len, return ret; } +int intel_guc_crash_process_msg(struct intel_guc *guc, u32 action) +{ + if (action == INTEL_GUC_ACTION_NOTIFY_CRASH_DUMP_POSTED) + guc_err(guc, "Crash dump notification\n"); + else if (action == INTEL_GUC_ACTION_NOTIFY_EXCEPTION) + guc_err(guc, "Exception notification\n"); + else + guc_err(guc, "Unknown crash notification: 0x%04X\n", action); + + queue_work(system_unbound_wq, >dead_guc_worker); + + return 0; +} + int intel_guc_to_host_process_recv_msg(struct intel_guc *guc, const u32 *payload, u32 len) { @@ -601,6 +634,9 @@ int intel_guc_to_host_process_recv_msg(struct intel_guc *guc, if (msg & INTEL_GUC_RECV_MSG_EXCEPTION) guc_err(guc, "Received early exception notification!\n"); + if (msg & (INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED | INTEL_GUC_RECV_MSG_EXCEPTION)) + queue_work(system_unbound_wq, >dead_guc_worker); + return 0; } @@ -640,6 +676,8 @@ int intel_guc_suspend(struct intel_guc *guc) return 0; if (intel_guc_submission_is_used(guc)) { + flush_work(>dead_guc_worker); + /* * This H2G MMIO command tears down the GuC in two steps. First it will * generate a G2H CTB for every active context indicating a reset. In diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 8dc291ff00935..6c392bad29c19 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -266,6 +266,20 @@ struct intel_guc { unsigned long last_stat_jiffies; } timestamp; + /** +* @dead_guc_worker: Asynchronous worker thread for forcing a GuC reset. +* Specifically used when the G2H handler wants to issue a reset. Resets +* require flushing the G2H queue. So, the G2H processing itself must not +
[Intel-gfx] [PATCH] drm/i915/guc: Fix potential null pointer deref in GuC 'steal id' test
From: John Harrison It was noticed that if the very first 'stealing' request failed to create for some reason then the 'steal all ids' loop would immediately exit with 'last' still being NULL. The test would attempt to continue but using a null pointer. Fix that by aborting the test if it fails to create any requests at all. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c index 1fd760539f77b..bfb72143566f6 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c @@ -204,9 +204,9 @@ static int intel_guc_steal_guc_ids(void *arg) if (IS_ERR(rq)) { ret = PTR_ERR(rq); rq = NULL; - if (ret != -EAGAIN) { - guc_err(guc, "Failed to create request %d: %pe\n", - context_index, ERR_PTR(ret)); + if ((ret != -EAGAIN) || !last) { + guc_err(guc, "Failed to create %srequest %d: %pe\n", + last ? "" : "first ", context_index, ERR_PTR(ret)); goto err_spin_rq; } } else { -- 2.39.1
[Intel-gfx] [PATCH] drm/i915/guc: Force a reset on internal GuC error
From: John Harrison If GuC hits an internal error (and survives long enough to report it to the KMD), it is basically toast and will stop until a GT reset and subsequent GuC reload is performed. Previously, the KMD just printed an error message and then waited for the heartbeat to eventually kick in and trigger a reset (assuming the heartbeat had not been disabled). Instead, force the reset immediately to guarantee that it happens and to eliminate the very long heartbeat delay. The captured error state is also more likely to be useful if captured at the time of the error rather than many seconds later. Note that it is not possible to trigger a reset from with the G2H handler itself. The reset prepare process involves flushing outstanding G2H contents. So a deadlock could result. Instead, the G2H handler queues a worker thread to do the reset asynchronously. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 26 +++ drivers/gpu/drm/i915/gt/uc/intel_guc.h| 9 drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 6 +- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 2eb891b270aec..c35cf10f52b56 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -159,6 +159,13 @@ static void gen11_disable_guc_interrupts(struct intel_guc *guc) gen11_reset_guc_interrupts(guc); } +static void guc_dead_worker_func(struct work_struct *w) +{ + struct intel_guc *guc = container_of(w, struct intel_guc, dead_guc_worker); + + intel_gt_handle_error(guc_to_gt(guc), ALL_ENGINES, I915_ERROR_CAPTURE, "dead GuC"); +} + void intel_guc_init_early(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -171,6 +178,8 @@ void intel_guc_init_early(struct intel_guc *guc) intel_guc_slpc_init_early(>slpc); intel_guc_rc_init_early(guc); + INIT_WORK(>dead_guc_worker, guc_dead_worker_func); + mutex_init(>send_mutex); spin_lock_init(>irq_lock); if (GRAPHICS_VER(i915) >= 11) { @@ -585,6 +594,20 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *request, u32 len, return ret; } +int intel_guc_crash_process_msg(struct intel_guc *guc, u32 action) +{ + if (action == INTEL_GUC_ACTION_NOTIFY_CRASH_DUMP_POSTED) + guc_err(guc, "Crash dump notification\n"); + else if (action == INTEL_GUC_ACTION_NOTIFY_EXCEPTION) + guc_err(guc, "Exception notification\n"); + else + guc_err(guc, "Unknown crash notification\n"); + + queue_work(system_unbound_wq, >dead_guc_worker); + + return 0; +} + int intel_guc_to_host_process_recv_msg(struct intel_guc *guc, const u32 *payload, u32 len) { @@ -601,6 +624,9 @@ int intel_guc_to_host_process_recv_msg(struct intel_guc *guc, if (msg & INTEL_GUC_RECV_MSG_EXCEPTION) guc_err(guc, "Received early exception notification!\n"); + if (msg & (INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED | INTEL_GUC_RECV_MSG_EXCEPTION)) + queue_work(system_unbound_wq, >dead_guc_worker); + return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 8dc291ff00935..0b54eec95fc00 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -266,6 +266,14 @@ struct intel_guc { unsigned long last_stat_jiffies; } timestamp; + /** +* @dead_guc_worker: Asynchronous worker thread for forcing a GuC reset. +* Specifically used when the G2H handler wants to issue a reset. Resets +* require flushing the G2H queue. So, the G2H processing itself must not +* trigger a reset directly. Instead, go via this worker. +*/ + struct work_struct dead_guc_worker; + #ifdef CONFIG_DRM_I915_SELFTEST /** * @number_guc_id_stolen: The number of guc_ids that have been stolen @@ -476,6 +484,7 @@ int intel_guc_engine_failure_process_msg(struct intel_guc *guc, const u32 *msg, u32 len); int intel_guc_error_capture_process_msg(struct intel_guc *guc, const u32 *msg, u32 len); +int intel_guc_crash_process_msg(struct intel_guc *guc, u32 action); struct intel_engine_cs * intel_guc_lookup_engine(struct intel_guc *guc, u8 guc_class, u8 instance); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index f28a3a83742dc..7b09ad6931021 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -1116,12 +1116,8 @@ static int ct_process_request(struct intel_guc_ct *ct, struct ct_incoming_msg *r ret = 0; break; case
[Intel-gfx] [PATCH] drm/i915/guc: Remove some obsolete definitions
From: John Harrison There were a bunch of defines and structures left over from an API update a very long time ago. Remove them. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 33 - 1 file changed, 33 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 4e57bd09d50d9..b4d56eccfb1f0 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -35,13 +35,6 @@ #define GUC_MAX_CONTEXT_ID 65535 #defineGUC_INVALID_CONTEXT_ID GUC_MAX_CONTEXT_ID -#define GUC_RENDER_ENGINE 0 -#define GUC_VIDEO_ENGINE 1 -#define GUC_BLITTER_ENGINE 2 -#define GUC_VIDEOENHANCE_ENGINE3 -#define GUC_VIDEO_ENGINE2 4 -#define GUC_MAX_ENGINES_NUM(GUC_VIDEO_ENGINE2 + 1) - #define GUC_RENDER_CLASS 0 #define GUC_VIDEO_CLASS1 #define GUC_VIDEOENHANCE_CLASS 2 @@ -499,32 +492,6 @@ struct guc_log_buffer_state { u32 version; } __packed; -struct guc_ctx_report { - u32 report_return_status; - u32 reserved1[64]; - u32 affected_count; - u32 reserved2[2]; -} __packed; - -/* GuC Shared Context Data Struct */ -struct guc_shared_ctx_data { - u32 addr_of_last_preempted_data_low; - u32 addr_of_last_preempted_data_high; - u32 addr_of_last_preempted_data_high_tmp; - u32 padding; - u32 is_mapped_to_proxy; - u32 proxy_ctx_id; - u32 engine_reset_ctx_id; - u32 media_reset_count; - u32 reserved1[8]; - u32 uk_last_ctx_switch_reason; - u32 was_reset; - u32 lrca_gpu_addr; - u64 execlist_ctx; - u32 reserved2[66]; - struct guc_ctx_report preempt_ctx_report[GUC_MAX_ENGINES_NUM]; -} __packed; - /* This action will be programmed in C1BC - SOFT_SCRATCH_15_REG */ enum intel_guc_recv_message { INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED = BIT(1), -- 2.39.1
[Intel-gfx] [PATCH 3/3] drm/i915/guc: Track all sent actions to GuC
From: Michal Wajdeczko For easier debug of any unexpected error responses from GuC that might be related to non-blocking fast requests, track action code (and stack if under DEBUG_GUC config) for every H2G request. Signed-off-by: Michal Wajdeczko Signed-off-by: John Harrison --- drivers/gpu/drm/i915/Kconfig.debug| 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 68 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 11 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 47e845353ffad..2d21930d55015 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -157,6 +157,7 @@ config DRM_I915_SW_FENCE_CHECK_DAG config DRM_I915_DEBUG_GUC bool "Enable additional driver debugging for GuC" depends on DRM_I915 + select STACKDEPOT default n help Choose this option to turn on extra driver debugging that may affect diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index 3a71bb582089e..4aa903be1317b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -376,6 +376,24 @@ void intel_guc_ct_disable(struct intel_guc_ct *ct) } } +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) +static void ct_track_lost_and_found(struct intel_guc_ct *ct, u32 fence, u32 action) +{ + unsigned int lost = fence % ARRAY_SIZE(ct->requests.lost_and_found); +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC) + unsigned long entries[SZ_32]; + unsigned int n; + + n = stack_trace_save(entries, ARRAY_SIZE(entries), 1); + + /* May be called under spinlock, so avoid sleeping */ + ct->requests.lost_and_found[lost].stack = stack_depot_save(entries, n, GFP_NOWAIT); +#endif + ct->requests.lost_and_found[lost].fence = fence; + ct->requests.lost_and_found[lost].action = action; +} +#endif + static u32 ct_get_next_fence(struct intel_guc_ct *ct) { /* For now it's trivial */ @@ -447,6 +465,11 @@ static int ct_write(struct intel_guc_ct *ct, } GEM_BUG_ON(tail > size); +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) + ct_track_lost_and_found(ct, fence, + FIELD_GET(GUC_HXG_EVENT_MSG_0_ACTION, action[0])); +#endif + /* * make sure H2G buffer update and LRC tail update (if this triggering a * submission) are visible before updating the descriptor tail @@ -953,6 +976,43 @@ static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg) return -EPIPE; } +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) +static bool ct_check_lost_and_found(struct intel_guc_ct *ct, u32 fence) +{ + unsigned int n; + char *buf = NULL; + bool found = false; + + lockdep_assert_held(>requests.lock); + + for (n = 0; n < ARRAY_SIZE(ct->requests.lost_and_found); n++) { + if (ct->requests.lost_and_found[n].fence != fence) + continue; + found = true; + +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC) + buf = kmalloc(SZ_4K, GFP_NOWAIT); + if (buf && stack_depot_snprint(ct->requests.lost_and_found[n].stack, + buf, SZ_4K, 0)) { + CT_ERROR(ct, "Fence %u was used by action %#04x sent at\n%s", +fence, ct->requests.lost_and_found[n].action, buf); + break; + } +#endif + CT_ERROR(ct, "Fence %u was used by action %#04x\n", +fence, ct->requests.lost_and_found[n].action); + break; + } + kfree(buf); + return found; +} +#else +static bool ct_check_lost_and_found(struct intel_guc_ct *ct, u32 fence) +{ + return false; +} +#endif + static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *response) { u32 len = FIELD_GET(GUC_CTB_MSG_0_NUM_DWORDS, response->msg[0]); @@ -996,9 +1056,11 @@ static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *r if (!found) { CT_ERROR(ct, "Unsolicited response message: len %u, data %#x (fence %u, last %u)\n", len, hxg[0], fence, ct->requests.last_fence); - list_for_each_entry(req, >requests.pending, link) - CT_ERROR(ct, "request %u awaits response\n", -req->fence); + if (!ct_check_lost_and_found(ct, fence)) { + list_for_each_entry(req, >requests.pending, link) + CT_ERROR(ct, "request %u awaits response\n", +req->fence); + } err = -ENOKEY; } spin_unlock_irqrestore(>requests.lock, flags); diff --git
[Intel-gfx] [PATCH 2/3] drm/i915/guc: Update log for unsolicited CTB response
From: Michal Wajdeczko Instead of printing message fence twice, include HXG header of the unexpected message and its len. Signed-off-by: Michal Wajdeczko Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index af52ed4ffc7fb..3a71bb582089e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -994,9 +994,8 @@ static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *r break; } if (!found) { - CT_ERROR(ct, "Unsolicited response (fence %u)\n", fence); - CT_ERROR(ct, "Could not find fence=%u, last_fence=%u\n", fence, -ct->requests.last_fence); + CT_ERROR(ct, "Unsolicited response message: len %u, data %#x (fence %u, last %u)\n", +len, hxg[0], fence, ct->requests.last_fence); list_for_each_entry(req, >requests.pending, link) CT_ERROR(ct, "request %u awaits response\n", req->fence); -- 2.39.1
[Intel-gfx] [PATCH 0/3] Use FAST_REQUEST mechanism for non-blocking H2G calls
From: John Harrison The GuC interface supports a mechanism for returning errors against non-blocking H2G calls. This is called FAST_REQUEST. Given that the call is asynchronous, matching the returned error up is difficult. However, getting any error at all back is better than no error. If any such errors are reported, then extra tracking support can be compiled in for manual debug. Signed-off-by: John Harrison Michal Wajdeczko (3): drm/i915/guc: Use FAST_REQUEST for non-blocking H2G calls drm/i915/guc: Update log for unsolicited CTB response drm/i915/guc: Track all sent actions to GuC drivers/gpu/drm/i915/Kconfig.debug| 1 + .../gpu/drm/i915/gt/uc/abi/guc_messages_abi.h | 30 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 79 --- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 11 +++ 4 files changed, 112 insertions(+), 9 deletions(-) -- 2.39.1
[Intel-gfx] [PATCH 1/3] drm/i915/guc: Use FAST_REQUEST for non-blocking H2G calls
From: Michal Wajdeczko In addition to the already defined REQUEST HXG message format, which is used when sender expects some confirmation or data, HXG protocol includes definition of the FAST REQUEST message, that may be used when sender does not expect any useful data to be returned. Using this instead of GUC_HXG_TYPE_EVENT for non-blocking CTB requests will allow GuC to send back GUC_HXG_TYPE_RESPONSE_FAILURE in case of errors. Note that it is not possible to return such errors to the caller, since this is for non-blocking calls and the related fence is not stored. Instead such messages are treated as unexpected, which will give an indication of potential GuC misprogramming that warrants extra debugging effort. Signed-off-by: Michal Wajdeczko Signed-off-by: John Harrison --- .../gpu/drm/i915/gt/uc/abi/guc_messages_abi.h | 30 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 6 ++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h index 7d5ba4d97d708..98eb4f46572b9 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h @@ -24,6 +24,7 @@ * | | 30:28 | **TYPE** - message type | * | | | - _`GUC_HXG_TYPE_REQUEST` = 0 | * | | | - _`GUC_HXG_TYPE_EVENT` = 1 | + * | | | - _`GUC_HXG_TYPE_FAST_REQUEST` = 2 | * | | | - _`GUC_HXG_TYPE_NO_RESPONSE_BUSY` = 3 | * | | | - _`GUC_HXG_TYPE_NO_RESPONSE_RETRY` = 5 | * | | | - _`GUC_HXG_TYPE_RESPONSE_FAILURE` = 6 | @@ -46,6 +47,7 @@ #define GUC_HXG_MSG_0_TYPE (0x7 << 28) #define GUC_HXG_TYPE_REQUEST 0u #define GUC_HXG_TYPE_EVENT 1u +#define GUC_HXG_TYPE_FAST_REQUEST2u #define GUC_HXG_TYPE_NO_RESPONSE_BUSY3u #define GUC_HXG_TYPE_NO_RESPONSE_RETRY 5u #define GUC_HXG_TYPE_RESPONSE_FAILURE6u @@ -89,6 +91,34 @@ #define GUC_HXG_REQUEST_MSG_0_ACTION (0x << 0) #define GUC_HXG_REQUEST_MSG_n_DATAnGUC_HXG_MSG_n_PAYLOAD +/** + * DOC: HXG Fast Request + * + * The `HXG Request`_ message should be used to initiate asynchronous activity + * for which confirmation or return data is not expected. + * + * If confirmation is required then `HXG Request`_ shall be used instead. + * + * The recipient of this message may only use `HXG Failure`_ message if it was + * unable to accept this request (like invalid data). + * + * Format of `HXG Fast Request`_ message is same as `HXG Request`_ except @TYPE. + * + * +---+---+--+ + * | | Bits | Description | + * +===+===+==+ + * | 0 |31 | ORIGIN - see `HXG Message`_ | + * | +---+--+ + * | | 30:28 | TYPE = `GUC_HXG_TYPE_FAST_REQUEST`_ | + * | +---+--+ + * | | 27:16 | DATA0 - see `HXG Request`_ | + * | +---+--+ + * | | 15:0 | ACTION - see `HXG Request`_ | + * +---+---+--+ + * |...| | DATAn - see `HXG Request`_ | + * +---+---+--+ + */ + /** * DOC: HXG Event * diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index a22e33f37cae6..af52ed4ffc7fb 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -426,11 +426,11 @@ static int ct_write(struct intel_guc_ct *ct, FIELD_PREP(GUC_CTB_MSG_0_NUM_DWORDS, len) | FIELD_PREP(GUC_CTB_MSG_0_FENCE, fence); - type = (flags & INTEL_GUC_CT_SEND_NB) ? GUC_HXG_TYPE_EVENT : + type = (flags & INTEL_GUC_CT_SEND_NB) ? GUC_HXG_TYPE_FAST_REQUEST : GUC_HXG_TYPE_REQUEST; hxg = FIELD_PREP(GUC_HXG_MSG_0_TYPE, type) | - FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION | - GUC_HXG_EVENT_MSG_0_DATA0, action[0]); + FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION | + GUC_HXG_REQUEST_MSG_0_DATA0, action[0]); CT_DEBUG(ct, "writing (tail %u) %*ph %*ph %*ph\n", tail, 4, , 4, ,
[Intel-gfx] [PATCH] drm/i915/guc: Fix confused register capture list creation
From: John Harrison The GuC has a completely separate engine class enum when referring to register capture lists, which combines render and compute. The driver was using the 'normal' GuC specific engine class enum instead. That meant that it thought it was defining a capture list for compute engines, the list was actually being applied to the GSC engine. And if a platform didn't have a render engine, then it would get no compute register captures at all. Fix that. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 36 ++- .../gpu/drm/i915/gt/uc/intel_guc_capture.c| 61 +-- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 9 +++ 3 files changed, 72 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 69ce06faf8cda..63724e17829a7 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -643,6 +643,39 @@ static void guc_init_golden_context(struct intel_guc *guc) GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size); } +static u32 guc_get_capture_engine_mask(struct iosys_map *info_map, u32 capture_class) +{ + u32 mask; + + switch (capture_class) { + case GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE: + mask = info_map_read(info_map, engine_enabled_masks[GUC_RENDER_CLASS]); + mask |= info_map_read(info_map, engine_enabled_masks[GUC_COMPUTE_CLASS]); + break; + + case GUC_CAPTURE_LIST_CLASS_VIDEO: + mask = info_map_read(info_map, engine_enabled_masks[GUC_VIDEO_CLASS]); + break; + + case GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE: + mask = info_map_read(info_map, engine_enabled_masks[GUC_VIDEOENHANCE_CLASS]); + break; + + case GUC_CAPTURE_LIST_CLASS_BLITTER: + mask = info_map_read(info_map, engine_enabled_masks[GUC_BLITTER_CLASS]); + break; + + case GUC_CAPTURE_LIST_CLASS_GSC_OTHER: + mask = info_map_read(info_map, engine_enabled_masks[GUC_GSC_OTHER_CLASS]); + break; + + default: + mask = 0; + } + + return mask; +} + static int guc_capture_prep_lists(struct intel_guc *guc) { @@ -678,9 +711,10 @@ guc_capture_prep_lists(struct intel_guc *guc) for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) { for (j = 0; j < GUC_MAX_ENGINE_CLASSES; j++) { + u32 engine_mask = guc_get_capture_engine_mask(_map, j); /* null list if we dont have said engine or list */ - if (!info_map_read(_map, engine_enabled_masks[j])) { + if (!engine_mask) { if (ads_is_mapped) { ads_blob_write(guc, ads.capture_class[i][j], null_ggtt); ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 1def0b6467c79..0ff864da92dfe 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -174,35 +174,31 @@ static const struct __guc_mmio_reg_descr empty_regs_list[] = { /* List of lists */ static const struct __guc_mmio_reg_descr_group gen8_lists[] = { MAKE_REGLIST(gen8_global_regs, PF, GLOBAL, 0), - MAKE_REGLIST(gen8_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), - MAKE_REGLIST(gen8_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), - MAKE_REGLIST(gen8_rc_class_regs, PF, ENGINE_CLASS, GUC_COMPUTE_CLASS), - MAKE_REGLIST(gen8_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_COMPUTE_CLASS), - MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), - MAKE_REGLIST(gen8_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), - MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), - MAKE_REGLIST(gen8_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), - MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS), - MAKE_REGLIST(gen8_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS), - MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_GSC_OTHER_CLASS), - MAKE_REGLIST(empty_regs_list, PF, ENGINE_INSTANCE, GUC_GSC_OTHER_CLASS), + MAKE_REGLIST(gen8_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), + MAKE_REGLIST(gen8_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO), + MAKE_REGLIST(gen8_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), +
[Intel-gfx] [PATCH] drm/i1915/guc: Fix probe injection CI failures after recent change
From: John Harrison A recent change bumped a 'notice' message up to 'error' level for debug builds to help trap incorrect configurations in CI systems. Unfortunaetly, tha error condition in question is triggered by the error injection probe test. So change the message again to be 'probe error' level instead. Signed-off-by: John Harrison Fixes: 760133d42f0a ("drm/i915/uc: Make unexpected firmware versions an error in debug builds") Cc: John Harrison Cc: Daniele Ceraolo Spurio Cc: Rodrigo Vivi Cc: Alan Previn Cc: Lucas De Marchi Cc: Jani Nikula --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 4ec7df9ed5ff3..e467d9af61876 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -18,7 +18,7 @@ #include "i915_reg.h" #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) -#define UNEXPECTED gt_err +#define UNEXPECTED gt_probe_error #else #define UNEXPECTED gt_notice #endif -- 2.39.1
[Intel-gfx] [PATCH 1/2] drm/i915/uc: Track patch level versions on reduced version firmware files
From: John Harrison When reduced version firmware files were added (matching major component being the only strict requirement), the minor version was still tracked and a notification reported if it was older. However, the patch version should really be tracked as well for the same reasons. The KMD can work without the change but if the effort has been taken to release a new firmware with the change then there must be a valid reason for doing so - important bug fix, security fix, etc. And in that case it would be good to alert the user if they are missing out on that new fix. v2: Use correct patch version number and drop redunant debug print (review by Daniele / CI results). Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 30 +++- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 6b71b9febd74c..55e50bd08d7ff 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -80,14 +80,14 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, */ #define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp) \ fw_def(METEORLAKE, 0, guc_mmp(mtl, 70, 6, 5)) \ - fw_def(DG2, 0, guc_maj(dg2, 70, 5)) \ - fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5)) \ + fw_def(DG2, 0, guc_maj(dg2, 70, 5, 1)) \ + fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 69, 0, 3)) \ - fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5)) \ + fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5, 1)) \ fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 70, 1, 1)) \ fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 69, 0, 3)) \ - fw_def(DG1, 0, guc_maj(dg1, 70, 5)) \ + fw_def(DG1, 0, guc_maj(dg1, 70, 5, 1)) \ fw_def(ROCKETLAKE, 0, guc_mmp(tgl, 70, 1, 1)) \ fw_def(TIGERLAKE,0, guc_mmp(tgl, 70, 1, 1)) \ fw_def(JASPERLAKE, 0, guc_mmp(ehl, 70, 1, 1)) \ @@ -141,7 +141,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, __stringify(patch_) ".bin" /* Minor for internal driver use, not part of file name */ -#define MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_) \ +#define MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_, patch_) \ __MAKE_UC_FW_PATH_MAJOR(prefix_, "guc", major_) #define MAKE_GUC_FW_PATH_MMP(prefix_, major_, minor_, patch_) \ @@ -197,9 +197,9 @@ struct __packed uc_fw_blob { { UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \ .legacy = true } -#define GUC_FW_BLOB(prefix_, major_, minor_) \ - UC_FW_BLOB_NEW(major_, minor_, 0, false, \ - MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_)) +#define GUC_FW_BLOB(prefix_, major_, minor_, patch_) \ + UC_FW_BLOB_NEW(major_, minor_, patch_, false, \ + MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_, patch_)) #define GUC_FW_BLOB_MMP(prefix_, major_, minor_, patch_) \ UC_FW_BLOB_OLD(major_, minor_, patch_, \ @@ -296,6 +296,7 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) uc_fw->file_wanted.path = blob->path; uc_fw->file_wanted.ver.major = blob->major; uc_fw->file_wanted.ver.minor = blob->minor; + uc_fw->file_wanted.ver.patch = blob->patch; uc_fw->loaded_via_gsc = blob->loaded_via_gsc; found = true; break; @@ -794,6 +795,9 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) } 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; } } @@ -801,12 +805,16 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) /* Preserve the version that was really wanted */ memcpy(_fw->file_wanted, _ideal, sizeof(uc_fw->file_wanted)); - gt_notice(gt, "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\n", + gt_notice(gt, "%s firmware %s (%d.%d.%d) is recommended, but only %s (%d.%d.%d) was found\n", intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_wanted.path, - uc_fw->file_wanted.ver.major, uc_fw->file_wanted.ver.minor, + uc_fw->file_wanted.ver.major, + uc_fw->file_wanted.ver.minor, + uc_fw->file_wanted.ver.patch,
[Intel-gfx] [PATCH 2/2] drm/i915/mtl: Update GuC firmware version for MTL to 70.6.6
From: John Harrison Also switch to using reduced version file naming as it is no longer such a work-in-progress and likely to change. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 55e50bd08d7ff..10e48cbcf494a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -79,7 +79,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, * security fixes, etc. to be enabled. */ #define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp) \ - fw_def(METEORLAKE, 0, guc_mmp(mtl, 70, 6, 5)) \ + fw_def(METEORLAKE, 0, guc_maj(mtl, 70, 6, 6)) \ fw_def(DG2, 0, guc_maj(dg2, 70, 5, 1)) \ fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)) \ -- 2.39.1
[Intel-gfx] [PATCH 0/2] Update MTL GuC firmware
From: John Harrison Update MTL to the latest GuC release and switch to using reduced version file names. Also, pull in a patch from an earlier series that is waiting to merge to prevent merge conflicts later. Signed-off-by: John Harrison John Harrison (2): drm/i915/uc: Track patch level versions on reduced version firmware files drm/i915/mtl: Update GuC firmware version for MTL to 70.6.6 drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 32 +++- 1 file changed, 20 insertions(+), 12 deletions(-) -- 2.39.1
[Intel-gfx] PR for new GuC v70.6.6 for MTL
The following changes since commit 312c61f5a6c9c6a313383a8f0c2b02711ec15262: amdgpu: update DCN 3.1.6 DMCUB firmware (2023-05-03 09:11:02 -0400) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm-firmware mtl_guc_70.6.6 for you to fetch changes up to 192ee6d1a7806620eeb6f8478e6a3ec6ea44821c: i915: Add GuC v70.6.6 for MTL (2023-05-03 06:45:11 -0700) John Harrison (1): i915: Add GuC v70.6.6 for MTL WHENCE | 3 +++ i915/mtl_guc_70.bin | Bin 0 -> 303936 bytes 2 files changed, 3 insertions(+) create mode 100644 i915/mtl_guc_70.bin
[Intel-gfx] [PATCH v3 6/6] drm/i915/uc: Make unexpected firmware versions an error in debug builds
From: John Harrison If the DEBUG_GEM config option is set then escalate the 'unexpected firmware version' message from a notice to an error. This will ensure that the CI system treats such occurences as a failure and logs a bug about it (or fails the pre-merge testing). Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 34 ++-- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 010c049609102..41ebd0ee0bb5e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -17,6 +17,12 @@ #include "i915_drv.h" #include "i915_reg.h" +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) +#define UNEXPECTED gt_err +#else +#define UNEXPECTED gt_notice +#endif + static inline struct intel_gt * uc_fw_to_gt(struct intel_uc_fw *uc_fw, enum intel_uc_fw_type type) { @@ -833,10 +839,10 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) 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) { - gt_notice(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); + 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; @@ -854,16 +860,16 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) /* Preserve the version that was really wanted */ memcpy(_fw->file_wanted, _ideal, sizeof(uc_fw->file_wanted)); - gt_notice(gt, "%s firmware %s (%d.%d.%d) is recommended, but only %s (%d.%d.%d) was found\n", - intel_uc_fw_type_repr(uc_fw->type), - uc_fw->file_wanted.path, - uc_fw->file_wanted.ver.major, - uc_fw->file_wanted.ver.minor, - uc_fw->file_wanted.ver.patch, - uc_fw->file_selected.path, - uc_fw->file_selected.ver.major, - uc_fw->file_selected.ver.minor, - uc_fw->file_selected.ver.patch); + UNEXPECTED(gt, "%s firmware %s (%d.%d.%d) is recommended, but only %s (%d.%d.%d) was found\n", + intel_uc_fw_type_repr(uc_fw->type), + uc_fw->file_wanted.path, + uc_fw->file_wanted.ver.major, + uc_fw->file_wanted.ver.minor, + uc_fw->file_wanted.ver.patch, + uc_fw->file_selected.path, + uc_fw->file_selected.ver.major, + uc_fw->file_selected.ver.minor, + uc_fw->file_selected.ver.patch); gt_info(gt, "Consider updating your linux-firmware pkg or downloading from %s\n", INTEL_UC_FIRMWARE_URL); } -- 2.39.1
[Intel-gfx] [PATCH v3 2/6] drm/i915/guc: Print status register when waiting for GuC to load
From: John Harrison If the GuC load is taking an excessively long time, the wait loop currently prints the GT frequency. Extend that to include the GuC status as well so we can see if the GuC is actually making progress or not. Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 0ff088a5e51a8..364d0d546ec82 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -191,8 +191,10 @@ static int guc_wait_ucode(struct intel_guc *guc) if (!ret || !success) break; - guc_dbg(guc, "load still in progress, count = %d, freq = %dMHz\n", - count, intel_rps_read_actual_frequency(>gt->rps)); + guc_dbg(guc, "load still in progress, count = %d, freq = %dMHz, status = 0x%08X [0x%02X/%02X]\n", + count, intel_rps_read_actual_frequency(>gt->rps), status, + REG_FIELD_GET(GS_BOOTROM_MASK, status), + REG_FIELD_GET(GS_UKERNEL_MASK, status)); } after = ktime_get(); delta = ktime_sub(after, before); -- 2.39.1
[Intel-gfx] [PATCH v3 5/6] drm/i915/uc: Reject duplicate entries in firmware table
From: John Harrison It was noticed that duplicate entries in the firmware table could cause an infinite loop in the firmware loading code if that entry failed to load. Duplicate entries are a bug anyway and so should never happen. Ensure they don't by tweaking the table validation code to reject duplicates. For full m/m/p files, that can be done by simply tweaking the patch level check to reject matching values. For reduced version entries, the filename itself must be compared. v2: Improve comment (review by Daniele) Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 26 +--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 64e19688788d1..010c049609102 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -319,7 +319,7 @@ static bool validate_fw_table_type(struct drm_i915_private *i915, enum intel_uc_ { const struct uc_fw_platform_requirement *fw_blobs; u32 fw_count; - int i; + int i, j; if (type >= ARRAY_SIZE(blobs_all)) { drm_err(>drm, "No blob array for %s\n", intel_uc_fw_type_repr(type)); @@ -334,6 +334,26 @@ static bool validate_fw_table_type(struct drm_i915_private *i915, enum intel_uc_ /* make sure the list is ordered as expected */ for (i = 1; i < fw_count; i++) { + /* Versionless file names must be unique per platform: */ + for (j = i + 1; j < fw_count; j++) { + /* Same platform? */ + if (fw_blobs[i].p != fw_blobs[j].p) + continue; + + if (fw_blobs[i].blob.path != fw_blobs[j].blob.path) + continue; + + drm_err(>drm, "Duplicate %s blobs: %s r%u %s%d.%d.%d [%s] matches %s%d.%d.%d [%s]\n", + intel_uc_fw_type_repr(type), + intel_platform_name(fw_blobs[j].p), fw_blobs[j].rev, + fw_blobs[j].blob.legacy ? "L" : "v", + fw_blobs[j].blob.major, fw_blobs[j].blob.minor, + fw_blobs[j].blob.patch, fw_blobs[j].blob.path, + fw_blobs[i].blob.legacy ? "L" : "v", + fw_blobs[i].blob.major, fw_blobs[i].blob.minor, + fw_blobs[i].blob.patch, fw_blobs[i].blob.path); + } + /* Next platform is good: */ if (fw_blobs[i].p < fw_blobs[i - 1].p) continue; @@ -377,8 +397,8 @@ static bool validate_fw_table_type(struct drm_i915_private *i915, enum intel_uc_ if (fw_blobs[i].blob.minor != fw_blobs[i - 1].blob.minor) goto bad; - /* Patch versions must be in order: */ - if (fw_blobs[i].blob.patch <= fw_blobs[i - 1].blob.patch) + /* Patch versions must be in order and unique: */ + if (fw_blobs[i].blob.patch < fw_blobs[i - 1].blob.patch) continue; bad: -- 2.39.1
[Intel-gfx] [PATCH v3 4/6] drm/i915/uc: Enhancements to firmware table validation
From: John Harrison The validation of the firmware table was being done inside the code for scanning the table for the next available firmware blob. Which is unnecessary. So pull it out into a separate function that is only called once per blob type at init time. Also, drop the CONFIG_SELFTEST requirement and make errors terminal. It was mentioned that potential issues with backports would not be caught by regular pre-merge CI as that only occurs on tip not stable branches. Making the validation unconditional and failing driver load on detecting of a problem ensures that such backports will also be validated correctly. This requires adding a firmware global flag to indicate an issue with any of the per firmware tables. This is done rather than adding a new state enum as a new enum value would be a much more invasive change - lots of places would need updating to support the new error state. Note also that this change means that a table error will cause the driver to wedge even on platforms that don't require firmware files. This is intentional as per the above backport concern - someone doing backports is not guaranteed to test on every platform that they may potential affect. So forcing a failure on all platforms ensures that the problem will be noticed and corrected immediately. v2: Change to unconditionally fail module load on a validation error (review feedback/discussion with Daniele). v3: Add a new flag to track table validation errors (review feedback/discussion with Daniele). Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_uc.c| 3 + drivers/gpu/drm/i915/gt/uc/intel_uc.h| 1 + drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 161 +-- 3 files changed, 99 insertions(+), 66 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 996168312340e..1381943b8973d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -432,6 +432,9 @@ static bool uc_is_wopcm_locked(struct intel_uc *uc) static int __uc_check_hw(struct intel_uc *uc) { + if (uc->fw_table_invalid) + return -EIO; + if (!intel_uc_supports_guc(uc)) return 0; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_uc.h index 5d0f1bcc381e8..d585524d94deb 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h @@ -36,6 +36,7 @@ struct intel_uc { struct drm_i915_gem_object *load_err_log; bool reset_in_progress; + bool fw_table_invalid; }; void intel_uc_init_early(struct intel_uc *uc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 55e50bd08d7ff..64e19688788d1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -233,20 +233,22 @@ struct fw_blobs_by_type { u32 count; }; +static const struct uc_fw_platform_requirement blobs_guc[] = { + INTEL_GUC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, GUC_FW_BLOB_MMP) +}; + +static const struct uc_fw_platform_requirement blobs_huc[] = { + INTEL_HUC_FIRMWARE_DEFS(MAKE_FW_LIST, HUC_FW_BLOB, HUC_FW_BLOB_MMP, HUC_FW_BLOB_GSC) +}; + +static const struct fw_blobs_by_type blobs_all[INTEL_UC_FW_NUM_TYPES] = { + [INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) }, + [INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) }, +}; + static void __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) { - static const struct uc_fw_platform_requirement blobs_guc[] = { - INTEL_GUC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, GUC_FW_BLOB_MMP) - }; - static const struct uc_fw_platform_requirement blobs_huc[] = { - INTEL_HUC_FIRMWARE_DEFS(MAKE_FW_LIST, HUC_FW_BLOB, HUC_FW_BLOB_MMP, HUC_FW_BLOB_GSC) - }; - static const struct fw_blobs_by_type blobs_all[INTEL_UC_FW_NUM_TYPES] = { - [INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) }, - [INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) }, - }; - static bool verified[INTEL_UC_FW_NUM_TYPES]; const struct uc_fw_platform_requirement *fw_blobs; enum intel_platform p = INTEL_INFO(i915)->platform; u32 fw_count; @@ -286,6 +288,11 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) continue; if (uc_fw->file_selected.path) { + /* +* Continuing an earlier search after a found blob failed to load. +* Once the previously chosen path has been found, clear it out +* and let the search continue from there. +*/ if (uc_fw->file_selected.path == blob->path)
[Intel-gfx] [PATCH v3 3/6] drm/i915/uc: Track patch level versions on reduced version firmware files
From: John Harrison When reduced version firmware files were added (matching major component being the only strict requirement), the minor version was still tracked and a notification reported if it was older. However, the patch version should really be tracked as well for the same reasons. The KMD can work without the change but if the effort has been taken to release a new firmware with the change then there must be a valid reason for doing so - important bug fix, security fix, etc. And in that case it would be good to alert the user if they are missing out on that new fix. v2: Use correct patch version number and drop redunant debug print (review by Daniele / CI results). Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 30 +++- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 6b71b9febd74c..55e50bd08d7ff 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -80,14 +80,14 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, */ #define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp) \ fw_def(METEORLAKE, 0, guc_mmp(mtl, 70, 6, 5)) \ - fw_def(DG2, 0, guc_maj(dg2, 70, 5)) \ - fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5)) \ + fw_def(DG2, 0, guc_maj(dg2, 70, 5, 1)) \ + fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 69, 0, 3)) \ - fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5)) \ + fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5, 1)) \ fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 70, 1, 1)) \ fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 69, 0, 3)) \ - fw_def(DG1, 0, guc_maj(dg1, 70, 5)) \ + fw_def(DG1, 0, guc_maj(dg1, 70, 5, 1)) \ fw_def(ROCKETLAKE, 0, guc_mmp(tgl, 70, 1, 1)) \ fw_def(TIGERLAKE,0, guc_mmp(tgl, 70, 1, 1)) \ fw_def(JASPERLAKE, 0, guc_mmp(ehl, 70, 1, 1)) \ @@ -141,7 +141,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, __stringify(patch_) ".bin" /* Minor for internal driver use, not part of file name */ -#define MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_) \ +#define MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_, patch_) \ __MAKE_UC_FW_PATH_MAJOR(prefix_, "guc", major_) #define MAKE_GUC_FW_PATH_MMP(prefix_, major_, minor_, patch_) \ @@ -197,9 +197,9 @@ struct __packed uc_fw_blob { { UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \ .legacy = true } -#define GUC_FW_BLOB(prefix_, major_, minor_) \ - UC_FW_BLOB_NEW(major_, minor_, 0, false, \ - MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_)) +#define GUC_FW_BLOB(prefix_, major_, minor_, patch_) \ + UC_FW_BLOB_NEW(major_, minor_, patch_, false, \ + MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_, patch_)) #define GUC_FW_BLOB_MMP(prefix_, major_, minor_, patch_) \ UC_FW_BLOB_OLD(major_, minor_, patch_, \ @@ -296,6 +296,7 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) uc_fw->file_wanted.path = blob->path; uc_fw->file_wanted.ver.major = blob->major; uc_fw->file_wanted.ver.minor = blob->minor; + uc_fw->file_wanted.ver.patch = blob->patch; uc_fw->loaded_via_gsc = blob->loaded_via_gsc; found = true; break; @@ -794,6 +795,9 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) } 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; } } @@ -801,12 +805,16 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) /* Preserve the version that was really wanted */ memcpy(_fw->file_wanted, _ideal, sizeof(uc_fw->file_wanted)); - gt_notice(gt, "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\n", + gt_notice(gt, "%s firmware %s (%d.%d.%d) is recommended, but only %s (%d.%d.%d) was found\n", intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_wanted.path, - uc_fw->file_wanted.ver.major, uc_fw->file_wanted.ver.minor, + uc_fw->file_wanted.ver.major, + uc_fw->file_wanted.ver.minor, + uc_fw->file_wanted.ver.patch,
[Intel-gfx] [PATCH v3 0/6] Improvements to uc firmare management
From: John Harrison Enhance the firmware table verification code to catch more potential errors and to generally improve the code itself. Track patch level version even on reduced version files to allow user notification of missing bug fixes. Detect another immediate failure case when loading GuC firmware. Treat more problems as fatal errors, at least for DEBUG builds. v2: Use correct patch version number, drop redundant debug print fail load on table validation error (review by Daniele / CI results). v3: Fix spelling typos, use a new bool for invalid firmware tables rather than a status enum (review feedback from Daniele). Signed-off-by: John Harrison John Harrison (6): drm/i915/guc: Decode another GuC load failure case drm/i915/guc: Print status register when waiting for GuC to load drm/i915/uc: Track patch level versions on reduced version firmware files drm/i915/uc: Enhancements to firmware table validation drm/i915/uc: Reject duplicate entries in firmware table drm/i915/uc: Make unexpected firmware versions an error in debug builds .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 12 +- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 3 + drivers/gpu/drm/i915/gt/uc/intel_uc.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 227 +++--- 5 files changed, 160 insertions(+), 84 deletions(-) -- 2.39.1
[Intel-gfx] [PATCH v3 1/6] drm/i915/guc: Decode another GuC load failure case
From: John Harrison Explain another potential firmware failure mode and early exit the long wait if hit. Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h index bcb1129b36102..dabeaf4f245f3 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h @@ -44,6 +44,7 @@ enum intel_guc_load_status { enum intel_bootrom_load_status { INTEL_BOOTROM_STATUS_NO_KEY_FOUND = 0x13, INTEL_BOOTROM_STATUS_AES_PROD_KEY_FOUND = 0x1A, + INTEL_BOOTROM_STATUS_PROD_KEY_CHECK_FAILURE = 0x2B, INTEL_BOOTROM_STATUS_RSA_FAILED = 0x50, INTEL_BOOTROM_STATUS_PAVPC_FAILED = 0x73, INTEL_BOOTROM_STATUS_WOPCM_FAILED = 0x74, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 6fda3aec5c66a..0ff088a5e51a8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -129,6 +129,7 @@ static inline bool guc_load_done(struct intel_uncore *uncore, u32 *status, bool case INTEL_BOOTROM_STATUS_RC6CTXCONFIG_FAILED: case INTEL_BOOTROM_STATUS_MPUMAP_INCORRECT: case INTEL_BOOTROM_STATUS_EXCEPTION: + case INTEL_BOOTROM_STATUS_PROD_KEY_CHECK_FAILURE: *success = false; return true; } @@ -219,6 +220,11 @@ static int guc_wait_ucode(struct intel_guc *guc) guc_info(guc, "firmware signature verification failed\n"); ret = -ENOEXEC; break; + + case INTEL_BOOTROM_STATUS_PROD_KEY_CHECK_FAILURE: + guc_info(guc, "firmware production part check failure\n"); + ret = -ENOEXEC; + break; } switch (ukernel) { -- 2.39.1
[Intel-gfx] [PATCH v2 3/4] drm/i915/guc: Capture list naming clean up
From: John Harrison Don't use 'xe_lp*' prefixes for register lists that are common with Gen8. Don't add Xe only GSC registers to pre-Xe devices that don't even have a GSC engine. Fix Xe_LP name. Don't use GEN9 as a prefix for register lists that contain all GEN8 registers. Rename the 'default_' register list prefix to 'gen8_' as that is the more accurate name. Signed-off-by: John Harrison --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c| 100 +- 1 file changed, 49 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 9184d2595e4ce..729a8fcf20dda 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -30,12 +30,12 @@ #define COMMON_BASE_GLOBAL \ { FORCEWAKE_MT, 0, 0, "FORCEWAKE" } -#define COMMON_GEN9BASE_GLOBAL \ +#define COMMON_GEN8BASE_GLOBAL \ { ERROR_GEN6, 0, 0, "ERROR_GEN6" }, \ { DONE_REG, 0, 0, "DONE_REG" }, \ { HSW_GTT_CACHE_EN, 0, 0, "HSW_GTT_CACHE_EN" } -#define GEN9_GLOBAL \ +#define GEN8_GLOBAL \ { GEN8_FAULT_TLB_DATA0, 0, 0, "GEN8_FAULT_TLB_DATA0" }, \ { GEN8_FAULT_TLB_DATA1, 0, 0, "GEN8_FAULT_TLB_DATA1" } @@ -96,67 +96,65 @@ { GEN12_SFC_DONE(2),0, 0, "SFC_DONE[2]" }, \ { GEN12_SFC_DONE(3),0, 0, "SFC_DONE[3]" } -/* XE_LPD - Global */ -static const struct __guc_mmio_reg_descr xe_lpd_global_regs[] = { +/* XE_LP Global */ +static const struct __guc_mmio_reg_descr xe_lp_global_regs[] = { COMMON_BASE_GLOBAL, - COMMON_GEN9BASE_GLOBAL, + COMMON_GEN8BASE_GLOBAL, COMMON_GEN12BASE_GLOBAL, }; -/* XE_LPD - Render / Compute Per-Class */ -static const struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = { +/* XE_LP Render / Compute Per-Class */ +static const struct __guc_mmio_reg_descr xe_lp_rc_class_regs[] = { COMMON_BASE_HAS_EU, COMMON_BASE_RENDER, COMMON_GEN12BASE_RENDER, }; -/* GEN9/XE_LPD - Render / Compute Per-Engine-Instance */ -static const struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = { +/* GEN8+ Render / Compute Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr gen8_rc_inst_regs[] = { COMMON_BASE_ENGINE_INSTANCE, }; -/* GEN9/XE_LPD - Media Decode/Encode Per-Engine-Instance */ -static const struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = { +/* GEN8+ Media Decode/Encode Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr gen8_vd_inst_regs[] = { COMMON_BASE_ENGINE_INSTANCE, }; -/* XE_LPD - Video Enhancement Per-Class */ -static const struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = { +/* XE_LP Video Enhancement Per-Class */ +static const struct __guc_mmio_reg_descr xe_lp_vec_class_regs[] = { COMMON_GEN12BASE_VEC, }; -/* GEN9/XE_LPD - Video Enhancement Per-Engine-Instance */ -static const struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = { +/* GEN8+ Video Enhancement Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr gen8_vec_inst_regs[] = { COMMON_BASE_ENGINE_INSTANCE, }; -/* GEN9/XE_LPD - Blitter Per-Engine-Instance */ -static const struct __guc_mmio_reg_descr xe_lpd_blt_inst_regs[] = { +/* GEN8+ Blitter Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr gen8_blt_inst_regs[] = { COMMON_BASE_ENGINE_INSTANCE, }; -/* XE_LPD - GSC Per-Engine-Instance */ -static const struct __guc_mmio_reg_descr xe_lpd_gsc_inst_regs[] = { +/* XE_LP - GSC Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr xe_lp_gsc_inst_regs[] = { COMMON_BASE_ENGINE_INSTANCE, }; -/* GEN9 - Global */ -static const struct __guc_mmio_reg_descr default_global_regs[] = { +/* GEN8 - Global */ +static const struct __guc_mmio_reg_descr gen8_global_regs[] = { COMMON_BASE_GLOBAL, - COMMON_GEN9BASE_GLOBAL, - GEN9_GLOBAL, + COMMON_GEN8BASE_GLOBAL, + GEN8_GLOBAL, }; -static const struct __guc_mmio_reg_descr default_rc_class_regs[] = { +static const struct __guc_mmio_reg_descr gen8_rc_class_regs[] = { COMMON_BASE_HAS_EU, COMMON_BASE_RENDER, }; /* - * Empty lists: - * GEN9/XE_LPD - Blitter Per-Class - * GEN9/XE_LPD - Media Decode/Encode Per-Class - * GEN9 - VEC Class + * Empty list to prevent warnings about unknown class/instance types + * as not all class/instanace types have entries on all platforms. */ static const struct __guc_mmio_reg_descr empty_regs_list[] = { }; @@ -174,37 +172,37 @@ static const struct __guc_mmio_reg_descr empty_regs_list[] = { } /* List of lists */ -static const struct __guc_mmio_reg_descr_group default_lists[] = { - MAKE_REGLIST(default_global_regs, PF, GLOBAL, 0), - MAKE_REGLIST(default_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), -
[Intel-gfx] [PATCH v2 0/4] Improvements to GuC error capture
From: John Harrison The GuC error capture list creation was including Gen8 registers on Xe platforms. While fixing that, it was noticed that there were other issues. The platform naming was wrong, the naming of lists was misleading, the steered register code was duplicated and steered registers were not included on all supported platforms. Separately, it was noticed that the capture list search was broken for virtual engines. So fix that up too. v2: Swuash the split patches into a single patch ready for merge. Also include an extra patch about capture lists and virtual engines. Signed-off-by: John Harrison John Harrison (4): drm/i915/guc: Don't capture Gen8 regs on Xe devices drm/i915/guc: Consolidate duplicated capture list code drm/i915/guc: Capture list naming clean up drm/i915/guc: Fix error capture for virtual engines .../gpu/drm/i915/gt/uc/intel_guc_capture.c| 242 -- .../gpu/drm/i915/gt/uc/intel_guc_capture.h| 3 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 32 ++- drivers/gpu/drm/i915/i915_gpu_error.c | 11 +- 4 files changed, 149 insertions(+), 139 deletions(-) -- 2.39.1
[Intel-gfx] [PATCH v2 1/4] drm/i915/guc: Don't capture Gen8 regs on Xe devices
From: John Harrison A pair of pre-Xe registers were being included in the Xe capture list. GuC was rejecting those as being invalid and logging errors about them. So, stop doing it. Signed-off-by: John Harrison Reviewed-by: Alan Previn Fixes: dce2bd542337 ("drm/i915/guc: Add Gen9 registers for GuC error state capture.") Cc: Alan Previn Cc: Umesh Nerlige Ramappa Cc: Lucas De Marchi Cc: John Harrison Cc: Jani Nikula Cc: Matt Roper Cc: Balasubramani Vivekanandan Cc: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index cf49188db6a6e..e0e793167d61b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -31,12 +31,14 @@ { FORCEWAKE_MT, 0, 0, "FORCEWAKE" } #define COMMON_GEN9BASE_GLOBAL \ - { GEN8_FAULT_TLB_DATA0, 0, 0, "GEN8_FAULT_TLB_DATA0" }, \ - { GEN8_FAULT_TLB_DATA1, 0, 0, "GEN8_FAULT_TLB_DATA1" }, \ { ERROR_GEN6, 0, 0, "ERROR_GEN6" }, \ { DONE_REG, 0, 0, "DONE_REG" }, \ { HSW_GTT_CACHE_EN, 0, 0, "HSW_GTT_CACHE_EN" } +#define GEN9_GLOBAL \ + { GEN8_FAULT_TLB_DATA0, 0, 0, "GEN8_FAULT_TLB_DATA0" }, \ + { GEN8_FAULT_TLB_DATA1, 0, 0, "GEN8_FAULT_TLB_DATA1" } + #define COMMON_GEN12BASE_GLOBAL \ { GEN12_FAULT_TLB_DATA0,0, 0, "GEN12_FAULT_TLB_DATA0" }, \ { GEN12_FAULT_TLB_DATA1,0, 0, "GEN12_FAULT_TLB_DATA1" }, \ @@ -142,6 +144,7 @@ static const struct __guc_mmio_reg_descr xe_lpd_gsc_inst_regs[] = { static const struct __guc_mmio_reg_descr default_global_regs[] = { COMMON_BASE_GLOBAL, COMMON_GEN9BASE_GLOBAL, + GEN9_GLOBAL, }; static const struct __guc_mmio_reg_descr default_rc_class_regs[] = { -- 2.39.1
[Intel-gfx] [PATCH v2 2/4] drm/i915/guc: Consolidate duplicated capture list code
From: John Harrison Remove 99% duplicated steered register list code. Also, include the pre-Xe steered registers in the pre-Xe list generation. Signed-off-by: John Harrison Reviewed-by: Alan Previn --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c| 112 +- 1 file changed, 29 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index e0e793167d61b..9184d2595e4ce 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -260,11 +260,15 @@ struct __ext_steer_reg { i915_mcr_reg_t reg; }; -static const struct __ext_steer_reg xe_extregs[] = { +static const struct __ext_steer_reg gen8_extregs[] = { {"GEN8_SAMPLER_INSTDONE", GEN8_SAMPLER_INSTDONE}, {"GEN8_ROW_INSTDONE", GEN8_ROW_INSTDONE} }; +static const struct __ext_steer_reg xehpg_extregs[] = { + {"XEHPG_INSTDONE_GEOM_SVG", XEHPG_INSTDONE_GEOM_SVG} +}; + static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext, const struct __ext_steer_reg *extlist, int slice_id, int subslice_id) @@ -295,8 +299,8 @@ __alloc_ext_regs(struct __guc_mmio_reg_descr_group *newlist, } static void -guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc, - const struct __guc_mmio_reg_descr_group *lists) +guc_capture_alloc_steered_lists(struct intel_guc *guc, + const struct __guc_mmio_reg_descr_group *lists) { struct intel_gt *gt = guc_to_gt(guc); int slice, subslice, iter, i, num_steer_regs, num_tot_regs = 0; @@ -304,74 +308,19 @@ guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc, struct __guc_mmio_reg_descr_group *extlists; struct __guc_mmio_reg_descr *extarray; struct sseu_dev_info *sseu; + bool has_xehpg_extregs; - /* In XE_LPD we only have steered registers for the render-class */ + /* steered registers currently only exist for the render-class */ list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF, GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS); /* skip if extlists was previously allocated */ if (!list || guc->capture->extlists) return; - num_steer_regs = ARRAY_SIZE(xe_extregs); - - sseu = >info.sseu; - for_each_ss_steering(iter, gt, slice, subslice) - num_tot_regs += num_steer_regs; - - if (!num_tot_regs) - return; - - /* allocate an extra for an end marker */ - extlists = kcalloc(2, sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL); - if (!extlists) - return; - - if (__alloc_ext_regs([0], list, num_tot_regs)) { - kfree(extlists); - return; - } - - extarray = extlists[0].extlist; - for_each_ss_steering(iter, gt, slice, subslice) { - for (i = 0; i < num_steer_regs; ++i) { - __fill_ext_reg(extarray, _extregs[i], slice, subslice); - ++extarray; - } - } - - guc->capture->extlists = extlists; -} - -static const struct __ext_steer_reg xehpg_extregs[] = { - {"XEHPG_INSTDONE_GEOM_SVG", XEHPG_INSTDONE_GEOM_SVG} -}; - -static bool __has_xehpg_extregs(u32 ipver) -{ - return (ipver >= IP_VER(12, 55)); -} - -static void -guc_capture_alloc_steered_lists_xe_hpg(struct intel_guc *guc, - const struct __guc_mmio_reg_descr_group *lists, - u32 ipver) -{ - struct intel_gt *gt = guc_to_gt(guc); - struct sseu_dev_info *sseu; - int slice, subslice, i, iter, num_steer_regs, num_tot_regs = 0; - const struct __guc_mmio_reg_descr_group *list; - struct __guc_mmio_reg_descr_group *extlists; - struct __guc_mmio_reg_descr *extarray; - - /* In XE_LP / HPG we only have render-class steering registers during error-capture */ - list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF, - GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS); - /* skip if extlists was previously allocated */ - if (!list || guc->capture->extlists) - return; + has_xehpg_extregs = GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 55); - num_steer_regs = ARRAY_SIZE(xe_extregs); - if (__has_xehpg_extregs(ipver)) + num_steer_regs = ARRAY_SIZE(gen8_extregs); + if (has_xehpg_extregs) num_steer_regs += ARRAY_SIZE(xehpg_extregs); sseu = >info.sseu; @@ -393,11 +342,12 @@ guc_capture_alloc_steered_lists_xe_hpg(struct intel_guc *guc, extarray = extlists[0].extlist; for_each_ss_steering(iter, gt, slice, subslice) { - for (i = 0; i
[Intel-gfx] [PATCH v2 4/4] drm/i915/guc: Fix error capture for virtual engines
From: John Harrison GuC based register dumps in error capture logs were basically broken for virtual engines. This can be seen in igt@gem_exec_balancer@hang: [IGT] gem_exec_balancer: starting subtest hang [drm] GPU HANG: ecode 12:4:e1524110, in gem_exec_balanc [6388] [drm] GT0: GUC: No register capture node found for 0x1005 / 0xFEDC311D [drm] GPU HANG: ecode 12:4:, in gem_exec_balanc [6388] [IGT] gem_exec_balancer: exiting, ret=0 The test causes a hang on both engines of a virtual engine context. The engine instance zero hang gets a valid error capture but the non-instance-zero hang does not. Fix that by scanning through the list of pending register captures when a hang notification for a virtual engine is received. That way, the hang can be assigned to the correct physical engine prior to starting the error capture process. So later on, when the error capture handler tries to find the engine register list, it looks for one on the correct engine. Also, sneak in a missing blank line before a comment in the node search code. v2: Fix null pointer deref on non-GuC platforms. Signed-off-by: John Harrison Reviewed-by: Alan Previn --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c| 31 ++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h| 3 ++ .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 32 --- drivers/gpu/drm/i915/i915_gpu_error.c | 11 +-- 4 files changed, 70 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 729a8fcf20dda..1def0b6467c79 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -1540,6 +1540,36 @@ void intel_guc_capture_free_node(struct intel_engine_coredump *ee) ee->guc_capture_node = NULL; } +bool intel_guc_capture_is_matching_engine(struct intel_gt *gt, + struct intel_context *ce, + struct intel_engine_cs *engine) +{ + struct __guc_capture_parsed_output *n; + struct intel_guc *guc; + + if (!gt || !ce || !engine) + return false; + + guc = >uc.guc; + if (!guc->capture) + return false; + + /* +* Look for a matching GuC reported error capture node from +* the internal output link-list based on lrca, guc-id and engine +* identification. +*/ + list_for_each_entry(n, >capture->outlist, link) { + if (n->eng_inst == GUC_ID_TO_ENGINE_INSTANCE(engine->guc_id) && + n->eng_class == GUC_ID_TO_ENGINE_CLASS(engine->guc_id) && + n->guc_id == ce->guc_id.id && + (n->lrca & CTX_GTT_ADDRESS_MASK) == (ce->lrc.lrca & CTX_GTT_ADDRESS_MASK)) + return true; + } + + return false; +} + void intel_guc_capture_get_matching_node(struct intel_gt *gt, struct intel_engine_coredump *ee, struct intel_context *ce) @@ -1555,6 +1585,7 @@ void intel_guc_capture_get_matching_node(struct intel_gt *gt, return; GEM_BUG_ON(ee->guc_capture_node); + /* * Look for a matching GuC reported error capture node from * the internal output link-list based on lrca, guc-id and engine diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index fbd3713c7832d..302256d45431d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -11,6 +11,7 @@ struct drm_i915_error_state_buf; struct guc_gt_system_info; struct intel_engine_coredump; +struct intel_engine_cs; struct intel_context; struct intel_gt; struct intel_guc; @@ -20,6 +21,8 @@ int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *m, const struct intel_engine_coredump *ee); void intel_guc_capture_get_matching_node(struct intel_gt *gt, struct intel_engine_coredump *ee, struct intel_context *ce); +bool intel_guc_capture_is_matching_engine(struct intel_gt *gt, struct intel_context *ce, + struct intel_engine_cs *engine); void intel_guc_capture_process(struct intel_guc *guc); int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, void **outptr); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index ee3e8352637f2..b93fe27b4eaae 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4697,13 +4697,37 @@ static void capture_error_state(struct intel_guc *guc, { struct intel_gt *gt =
[Intel-gfx] [PATCH 6/6] drm/i915/guc: Capture list clean up - 5
From: John Harrison Rename the 'default_' register list prefix to 'gen8_' as that is the more accurate name. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index c1a75a2d17f1e..729a8fcf20dda 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -141,13 +141,13 @@ static const struct __guc_mmio_reg_descr xe_lp_gsc_inst_regs[] = { }; /* GEN8 - Global */ -static const struct __guc_mmio_reg_descr default_global_regs[] = { +static const struct __guc_mmio_reg_descr gen8_global_regs[] = { COMMON_BASE_GLOBAL, COMMON_GEN8BASE_GLOBAL, GEN8_GLOBAL, }; -static const struct __guc_mmio_reg_descr default_rc_class_regs[] = { +static const struct __guc_mmio_reg_descr gen8_rc_class_regs[] = { COMMON_BASE_HAS_EU, COMMON_BASE_RENDER, }; @@ -172,11 +172,11 @@ static const struct __guc_mmio_reg_descr empty_regs_list[] = { } /* List of lists */ -static const struct __guc_mmio_reg_descr_group default_lists[] = { - MAKE_REGLIST(default_global_regs, PF, GLOBAL, 0), - MAKE_REGLIST(default_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), +static const struct __guc_mmio_reg_descr_group gen8_lists[] = { + MAKE_REGLIST(gen8_global_regs, PF, GLOBAL, 0), + MAKE_REGLIST(gen8_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), MAKE_REGLIST(gen8_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), - MAKE_REGLIST(default_rc_class_regs, PF, ENGINE_CLASS, GUC_COMPUTE_CLASS), + MAKE_REGLIST(gen8_rc_class_regs, PF, ENGINE_CLASS, GUC_COMPUTE_CLASS), MAKE_REGLIST(gen8_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_COMPUTE_CLASS), MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), MAKE_REGLIST(gen8_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), @@ -366,7 +366,7 @@ guc_capture_get_device_reglist(struct intel_guc *guc) if (GRAPHICS_VER(i915) >= 12) lists = xe_lp_lists; else - lists = default_lists; + lists = gen8_lists; /* * For certain engine classes, there are slice and subslice -- 2.39.1
[Intel-gfx] [PATCH i-g-t 1/2] lib/intel_decode: Decode Gen12 ring/batch instructions correctly
From: John Harrison Some MI_ instructions have changed (or are just new) for Gen12. So update the decoder code to match. Signed-off-by: John Harrison --- lib/i915/intel_decode.c | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/i915/intel_decode.c b/lib/i915/intel_decode.c index 80b92d90c61c..1b6de5edafad 100644 --- a/lib/i915/intel_decode.c +++ b/lib/i915/intel_decode.c @@ -236,7 +236,7 @@ decode_mi(struct intel_decode *ctx) { 0x08, 0, 1, 1, "MI_ARB_ON_OFF" }, { 0x0a, 0, 1, 1, "MI_BATCH_BUFFER_END" }, { 0x30, 0x3f, 3, 3, "MI_BATCH_BUFFER" }, - { 0x31, 0x3f, 2, 2, "MI_BATCH_BUFFER_START" }, + { 0x31, 0x3f, 2, 3, "MI_BATCH_BUFFER_START" }, { 0x14, 0x3f, 3, 3, "MI_DISPLAY_BUFFER_INFO" }, { 0x04, 0, 1, 1, "MI_FLUSH" }, { 0x22, 0x1f, 3, 3, "MI_LOAD_REGISTER_IMM" }, @@ -256,6 +256,7 @@ decode_mi(struct intel_decode *ctx) { 0x28, 0x3f, 3, 3, "MI_REPORT_PERF_COUNT" }, { 0x29, 0xff, 3, 3, "MI_LOAD_REGISTER_MEM" }, { 0x0b, 0, 1, 1, "MI_SUSPEND_FLUSH"}, + { 0x05, 0, 1, 1, "MI_ARB_CHECK"}, }, *opcode_mi = NULL; /* check instruction length */ @@ -3623,7 +3624,17 @@ decode_3d_965(struct intel_decode *ctx) return len; case 0x7a00: - if (IS_GEN6(devid) || IS_GEN7(devid)) { + if (IS_GEN12(devid)) { + if (len != 6) + fprintf(out, "Bad count in PIPE_CONTROL\n"); + instr_out(ctx, 0, "PIPE_CONTROL\n"); + instr_out(ctx, 1, "flags\n"); + instr_out(ctx, 2, "write address low\n"); + instr_out(ctx, 3, "write address high\n"); + instr_out(ctx, 4, "write data low\n"); + instr_out(ctx, 5, "write data high\n"); + return len; + } else if (IS_GEN6(devid) || IS_GEN7(devid)) { if (len != 4 && len != 5) fprintf(out, "Bad count in PIPE_CONTROL\n"); -- 2.39.1
[Intel-gfx] [PATCH i-g-t 0/2] Update intel_error_decode for Gen12
From: John Harrison The error capture decoder was reporting invalid errors in batch buffers and getting confused about the prescence of the GuC CTB. So fix those up. Signed-off-by: John Harrison John Harrison (2): lib/intel_decode: Decode Gen12 ring/batch instructions correctly tools/intel_error_decode: Correctly name the GuC CT buffer lib/i915/intel_decode.c| 15 +-- tools/intel_error_decode.c | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) -- 2.39.1
[Intel-gfx] [PATCH i-g-t 2/2] tools/intel_error_decode: Correctly name the GuC CT buffer
From: John Harrison The buffer decoding code doesn't cope well with unknown buffers. So add an entry for the GuC CTB so that it gets decoded correctly. Signed-off-by: John Harrison --- tools/intel_error_decode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/intel_error_decode.c b/tools/intel_error_decode.c index 99680bedc785..451608826be3 100644 --- a/tools/intel_error_decode.c +++ b/tools/intel_error_decode.c @@ -617,6 +617,7 @@ read_data_file(FILE *file) { "user", "user", 0 }, { "semaphores", "semaphores", 0 }, { "guc log buffer", "GuC log", 0 }, + { "guc ct buffer", "GuC CTB", 0 }, { }, }, *b; char *new_ring_name; -- 2.39.1
[Intel-gfx] [PATCH] drm/i915/guc: Actually return an error if GuC version range check fails
From: John Harrison Dan Carpenter pointed out that 'err' was not being set in the case where the GuC firmware version range check fails. Fix that. Note that while this is bug fix for a previous patch (see Fixes tag below). It is an exceedingly low risk bug. The range check is asserting that the GuC firmware version is within spec. So it should not be possible to ever have a firmware file that fails this check. If larger version numbers are required in the future, that would be a backwards breaking spec change and thus require a major version bump, in which case an old i915 driver would not load that new version anyway. Fixes: 9bbba0667f37 ("drm/i915/guc: Use GuC submission API version number") Reported-by: Dan Carpenter Signed-off-by: John Harrison Cc: John Harrison Cc: Daniele Ceraolo Spurio Cc: Alan Previn Cc: Umesh Nerlige Ramappa Cc: Rodrigo Vivi Cc: Matthew Brost Cc: Andi Shyti Cc: Matthew Auld Cc: Tvrtko Ursulin Cc: Lucas De Marchi Cc: Jani Nikula --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 20 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index a82a53dbbc86d..6b71b9febd74c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -636,9 +636,10 @@ static bool is_ver_8bit(struct intel_uc_fw_ver *ver) return ver->major < 0xFF && ver->minor < 0xFF && ver->patch < 0xFF; } -static bool guc_check_version_range(struct intel_uc_fw *uc_fw) +static int guc_check_version_range(struct intel_uc_fw *uc_fw) { struct intel_guc *guc = container_of(uc_fw, struct intel_guc, fw); + struct intel_gt *gt = __uc_fw_to_gt(uc_fw); /* * GuC version number components are defined as being 8-bits. @@ -647,24 +648,24 @@ static bool guc_check_version_range(struct intel_uc_fw *uc_fw) */ if (!is_ver_8bit(_fw->file_selected.ver)) { - gt_warn(__uc_fw_to_gt(uc_fw), "%s firmware: invalid file version: 0x%02X:%02X:%02X\n", + gt_warn(gt, "%s firmware: invalid file version: 0x%02X:%02X:%02X\n", intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.ver.major, uc_fw->file_selected.ver.minor, uc_fw->file_selected.ver.patch); - return false; + return -EINVAL; } if (!is_ver_8bit(>submission_version)) { - gt_warn(__uc_fw_to_gt(uc_fw), "%s firmware: invalid submit version: 0x%02X:%02X:%02X\n", + gt_warn(gt, "%s firmware: invalid submit version: 0x%02X:%02X:%02X\n", intel_uc_fw_type_repr(uc_fw->type), guc->submission_version.major, guc->submission_version.minor, guc->submission_version.patch); - return false; + return -EINVAL; } - return true; + return i915_inject_probe_error(gt->i915, -EINVAL); } static int check_fw_header(struct intel_gt *gt, @@ -773,8 +774,11 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) if (err) goto fail; - if (uc_fw->type == INTEL_UC_FW_TYPE_GUC && !guc_check_version_range(uc_fw)) - goto fail; + if (uc_fw->type == INTEL_UC_FW_TYPE_GUC) { + err = guc_check_version_range(uc_fw); + if (err) + 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 */ -- 2.39.1
[Intel-gfx] [PATCH 4/6] drm/i915/uc: Enhancements to firmware table validation
From: John Harrison The validation of the firmware table was being done inside the code for scanning the table for the next available firmware blob. Which is unnecessary. So pull it out into a separate function that is only called once per blob type at init time. Also, drop the CONFIG_SELFTEST requirement and make errors terminal. It was mentioned that potential issues with backports would not be caught by regular pre-merge CI as that only occurs on tip not stable branches. Making the validation unconditional and failing driver load on detecting of a problem ensures that such backports will also be validated correctly. v2: Change to unconditionally fail module load on a validation error (review feedback/discussion with Daniele). Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 157 +-- 1 file changed, 92 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index c9cd9bb47577f..eb52e8db9ae0b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -233,20 +233,22 @@ struct fw_blobs_by_type { u32 count; }; +static const struct uc_fw_platform_requirement blobs_guc[] = { + INTEL_GUC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, GUC_FW_BLOB_MMP) +}; + +static const struct uc_fw_platform_requirement blobs_huc[] = { + INTEL_HUC_FIRMWARE_DEFS(MAKE_FW_LIST, HUC_FW_BLOB, HUC_FW_BLOB_MMP, HUC_FW_BLOB_GSC) +}; + +static const struct fw_blobs_by_type blobs_all[INTEL_UC_FW_NUM_TYPES] = { + [INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) }, + [INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) }, +}; + static void __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) { - static const struct uc_fw_platform_requirement blobs_guc[] = { - INTEL_GUC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, GUC_FW_BLOB_MMP) - }; - static const struct uc_fw_platform_requirement blobs_huc[] = { - INTEL_HUC_FIRMWARE_DEFS(MAKE_FW_LIST, HUC_FW_BLOB, HUC_FW_BLOB_MMP, HUC_FW_BLOB_GSC) - }; - static const struct fw_blobs_by_type blobs_all[INTEL_UC_FW_NUM_TYPES] = { - [INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) }, - [INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) }, - }; - static bool verified[INTEL_UC_FW_NUM_TYPES]; const struct uc_fw_platform_requirement *fw_blobs; enum intel_platform p = INTEL_INFO(i915)->platform; u32 fw_count; @@ -286,6 +288,11 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) continue; if (uc_fw->file_selected.path) { + /* +* Continuing an earlier search after a found blob failed to load. +* Once the previously chosen path has been found, clear it out +* and let the search continue from there. +*/ if (uc_fw->file_selected.path == blob->path) uc_fw->file_selected.path = NULL; @@ -306,76 +313,91 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) /* Failed to find a match for the last attempt?! */ uc_fw->file_selected.path = NULL; } +} - /* make sure the list is ordered as expected */ - if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST) && !verified[uc_fw->type]) { - verified[uc_fw->type] = true; +static bool validate_fw_table_type(struct drm_i915_private *i915, enum intel_uc_fw_type type) +{ + const struct uc_fw_platform_requirement *fw_blobs; + u32 fw_count; + int i; - for (i = 1; i < fw_count; i++) { - /* Next platform is good: */ - if (fw_blobs[i].p < fw_blobs[i - 1].p) - continue; + if (type >= ARRAY_SIZE(blobs_all)) { + drm_err(>drm, "No blob array for %s\n", intel_uc_fw_type_repr(type)); + return false; + } - /* Next platform revision is good: */ - if (fw_blobs[i].p == fw_blobs[i - 1].p && - fw_blobs[i].rev < fw_blobs[i - 1].rev) - continue; + fw_blobs = blobs_all[type].blobs; + fw_count = blobs_all[type].count; - /* Platform/revision must be in order: */ - if (fw_blobs[i].p != fw_blobs[i - 1].p || - fw_blobs[i].rev != fw_blobs[i - 1].rev) - goto bad; + if (!fw_count) + return true; - /* Next major version is good: */ - if (fw_blobs[i].blob.major < fw_blobs[i -
[Intel-gfx] [PATCH 6/6] drm/i915/uc: Make unexpected firmware versions an error in debug builds
From: John Harrison If the DEBUG_GEM config option is set then escalate the 'unexpected firmware version' message from a notice to an error. This will ensure that the CI system treats such occurences as a failure and logs a bug about it (or fails the pre-merge testing). Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 34 ++-- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index bc4011d55667c..c5b21d17ca437 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -17,6 +17,12 @@ #include "i915_drv.h" #include "i915_reg.h" +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) +#define UNEXPECTED gt_err +#else +#define UNEXPECTED gt_notice +#endif + static inline struct intel_gt * uc_fw_to_gt(struct intel_uc_fw *uc_fw, enum intel_uc_fw_type type) { @@ -828,10 +834,10 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) 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) { - gt_notice(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); + 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; @@ -849,16 +855,16 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) /* Preserve the version that was really wanted */ memcpy(_fw->file_wanted, _ideal, sizeof(uc_fw->file_wanted)); - gt_notice(gt, "%s firmware %s (%d.%d.%d) is recommended, but only %s (%d.%d.%d) was found\n", - intel_uc_fw_type_repr(uc_fw->type), - uc_fw->file_wanted.path, - uc_fw->file_wanted.ver.major, - uc_fw->file_wanted.ver.minor, - uc_fw->file_wanted.ver.patch, - uc_fw->file_selected.path, - uc_fw->file_selected.ver.major, - uc_fw->file_selected.ver.minor, - uc_fw->file_selected.ver.patch); + UNEXPECTED(gt, "%s firmware %s (%d.%d.%d) is recommended, but only %s (%d.%d.%d) was found\n", + intel_uc_fw_type_repr(uc_fw->type), + uc_fw->file_wanted.path, + uc_fw->file_wanted.ver.major, + uc_fw->file_wanted.ver.minor, + uc_fw->file_wanted.ver.patch, + uc_fw->file_selected.path, + uc_fw->file_selected.ver.major, + uc_fw->file_selected.ver.minor, + uc_fw->file_selected.ver.patch); gt_info(gt, "Consider updating your linux-firmware pkg or downloading from %s\n", INTEL_UC_FIRMWARE_URL); } -- 2.39.1
[Intel-gfx] [PATCH 5/6] drm/i915/uc: Reject duplicate entries in firmware table
From: John Harrison It was noticed that duplicate entries in the firmware table could cause an infinite loop in the firmware loading code if that entry failed to load. Duplicate entries are a bug anyway and so should never happen. Ensure they don't by tweaking the table validation code to reject duplicates. For full m/m/p files, that can be done by simply tweaking the patch level check to reject matching values. For reduced version entries, the filename itself must be compared. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 27 +--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index eb52e8db9ae0b..bc4011d55667c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -319,7 +319,7 @@ static bool validate_fw_table_type(struct drm_i915_private *i915, enum intel_uc_ { const struct uc_fw_platform_requirement *fw_blobs; u32 fw_count; - int i; + int i, j; if (type >= ARRAY_SIZE(blobs_all)) { drm_err(>drm, "No blob array for %s\n", intel_uc_fw_type_repr(type)); @@ -334,6 +334,27 @@ static bool validate_fw_table_type(struct drm_i915_private *i915, enum intel_uc_ /* make sure the list is ordered as expected */ for (i = 1; i < fw_count; i++) { + /* Versionless file names must be unique per platform: */ + for (j = i + 1; j < fw_count; j++) { + /* Same platform? */ + if (fw_blobs[i].p != fw_blobs[j].p) + continue; + + if (fw_blobs[i].blob.path != fw_blobs[j].blob.path) + continue; + + drm_err(>drm, "Diplicaate %s blobs: %s r%u %s%d.%d.%d [%s] matches %s r%u %s%d.%d.%d [%s]\n", + intel_uc_fw_type_repr(type), + intel_platform_name(fw_blobs[j].p), fw_blobs[j].rev, + fw_blobs[j].blob.legacy ? "L" : "v", + fw_blobs[j].blob.major, fw_blobs[j].blob.minor, + fw_blobs[j].blob.patch, fw_blobs[j].blob.path, + intel_platform_name(fw_blobs[i].p), fw_blobs[i].rev, + fw_blobs[i].blob.legacy ? "L" : "v", + fw_blobs[i].blob.major, fw_blobs[i].blob.minor, + fw_blobs[i].blob.patch, fw_blobs[i].blob.path); + } + /* Next platform is good: */ if (fw_blobs[i].p < fw_blobs[i - 1].p) continue; @@ -377,8 +398,8 @@ static bool validate_fw_table_type(struct drm_i915_private *i915, enum intel_uc_ if (fw_blobs[i].blob.minor != fw_blobs[i - 1].blob.minor) goto bad; - /* Patch versions must be in order: */ - if (fw_blobs[i].blob.patch <= fw_blobs[i - 1].blob.patch) + /* Patch versions must be in order and unique: */ + if (fw_blobs[i].blob.patch < fw_blobs[i - 1].blob.patch) continue; bad: -- 2.39.1
[Intel-gfx] [PATCH 1/6] drm/i915/guc: Decode another GuC load failure case
From: John Harrison Explain another potential firmware failure mode and early exit the long wait if hit. Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 6 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h index bcb1129b36102..dabeaf4f245f3 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h @@ -44,6 +44,7 @@ enum intel_guc_load_status { enum intel_bootrom_load_status { INTEL_BOOTROM_STATUS_NO_KEY_FOUND = 0x13, INTEL_BOOTROM_STATUS_AES_PROD_KEY_FOUND = 0x1A, + INTEL_BOOTROM_STATUS_PROD_KEY_CHECK_FAILURE = 0x2B, INTEL_BOOTROM_STATUS_RSA_FAILED = 0x50, INTEL_BOOTROM_STATUS_PAVPC_FAILED = 0x73, INTEL_BOOTROM_STATUS_WOPCM_FAILED = 0x74, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 6fda3aec5c66a..0ff088a5e51a8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -129,6 +129,7 @@ static inline bool guc_load_done(struct intel_uncore *uncore, u32 *status, bool case INTEL_BOOTROM_STATUS_RC6CTXCONFIG_FAILED: case INTEL_BOOTROM_STATUS_MPUMAP_INCORRECT: case INTEL_BOOTROM_STATUS_EXCEPTION: + case INTEL_BOOTROM_STATUS_PROD_KEY_CHECK_FAILURE: *success = false; return true; } @@ -219,6 +220,11 @@ static int guc_wait_ucode(struct intel_guc *guc) guc_info(guc, "firmware signature verification failed\n"); ret = -ENOEXEC; break; + + case INTEL_BOOTROM_STATUS_PROD_KEY_CHECK_FAILURE: + guc_info(guc, "firmware production part check failure\n"); + ret = -ENOEXEC; + break; } switch (ukernel) { -- 2.39.1
[Intel-gfx] [PATCH 3/6] drm/i915/uc: Track patch level versions on reduced version firmware files
From: John Harrison When reduced version firmware files were added (matching major component being the only strict requirement), the minor version was still tracked and a notification reported if it was older. However, the patch version should really be tracked as well for the same reasons. The KMD can work without the change but if the effort has been taken to release a new firmware with the change then there must be a valid reason for doing so - important bug fix, security fix, etc. And in that case it would be good to alert the user if they are missing out on that new fix. v2: Use correct patch version number and drop redunant debug print (review by Daniele / CI results). Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 30 +++- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index a82a53dbbc86d..c9cd9bb47577f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -80,14 +80,14 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, */ #define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp) \ fw_def(METEORLAKE, 0, guc_mmp(mtl, 70, 6, 5)) \ - fw_def(DG2, 0, guc_maj(dg2, 70, 5)) \ - fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5)) \ + fw_def(DG2, 0, guc_maj(dg2, 70, 5, 1)) \ + fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)) \ fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 69, 0, 3)) \ - fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5)) \ + fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5, 1)) \ fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 70, 1, 1)) \ fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 69, 0, 3)) \ - fw_def(DG1, 0, guc_maj(dg1, 70, 5)) \ + fw_def(DG1, 0, guc_maj(dg1, 70, 5, 1)) \ fw_def(ROCKETLAKE, 0, guc_mmp(tgl, 70, 1, 1)) \ fw_def(TIGERLAKE,0, guc_mmp(tgl, 70, 1, 1)) \ fw_def(JASPERLAKE, 0, guc_mmp(ehl, 70, 1, 1)) \ @@ -141,7 +141,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, __stringify(patch_) ".bin" /* Minor for internal driver use, not part of file name */ -#define MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_) \ +#define MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_, patch_) \ __MAKE_UC_FW_PATH_MAJOR(prefix_, "guc", major_) #define MAKE_GUC_FW_PATH_MMP(prefix_, major_, minor_, patch_) \ @@ -197,9 +197,9 @@ struct __packed uc_fw_blob { { UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \ .legacy = true } -#define GUC_FW_BLOB(prefix_, major_, minor_) \ - UC_FW_BLOB_NEW(major_, minor_, 0, false, \ - MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_)) +#define GUC_FW_BLOB(prefix_, major_, minor_, patch_) \ + UC_FW_BLOB_NEW(major_, minor_, patch_, false, \ + MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_, patch_)) #define GUC_FW_BLOB_MMP(prefix_, major_, minor_, patch_) \ UC_FW_BLOB_OLD(major_, minor_, patch_, \ @@ -296,6 +296,7 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) uc_fw->file_wanted.path = blob->path; uc_fw->file_wanted.ver.major = blob->major; uc_fw->file_wanted.ver.minor = blob->minor; + uc_fw->file_wanted.ver.patch = blob->patch; uc_fw->loaded_via_gsc = blob->loaded_via_gsc; found = true; break; @@ -790,6 +791,9 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) } 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; } } @@ -797,12 +801,16 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) /* Preserve the version that was really wanted */ memcpy(_fw->file_wanted, _ideal, sizeof(uc_fw->file_wanted)); - gt_notice(gt, "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\n", + gt_notice(gt, "%s firmware %s (%d.%d.%d) is recommended, but only %s (%d.%d.%d) was found\n", intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_wanted.path, - uc_fw->file_wanted.ver.major, uc_fw->file_wanted.ver.minor, + uc_fw->file_wanted.ver.major, + uc_fw->file_wanted.ver.minor, + uc_fw->file_wanted.ver.patch,
[Intel-gfx] [PATCH 0/6] Improvements to uc firmare management
From: John Harrison Enhance the firmware table verification code to catch more potential errors and to generally improve the code itself. Track patch level version even on reduced version files to allow user notification of missing bug fixes. Detect another immediate failure case when loading GuC firmware. Treat more problems as fatal errors, at least for DEBUG builds. Signed-off-by: John Harrison John Harrison (6): drm/i915/guc: Decode another GuC load failure case drm/i915/guc: Print status register when waiting for GuC to load drm/i915/uc: Track patch level versions on reduced version firmware files drm/i915/uc: Enhancements to firmware table validation drm/i915/uc: Reject duplicate entries in firmware table drm/i915/uc: Make unexpected firmware versions an error in debug builds .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 12 +- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 224 +++--- 3 files changed, 154 insertions(+), 83 deletions(-) -- 2.39.1