drm/xe/lnl: Apply GuC Wa_13011645652
authorVinay Belgaumkar <vinay.belgaumkar@intel.com>
Wed, 17 Apr 2024 05:48:02 +0000 (22:48 -0700)
committerJohn Harrison <John.C.Harrison@Intel.com>
Wed, 17 Apr 2024 22:21:12 +0000 (15:21 -0700)
Enable WA for a bug that could cause the C6 state machine to hang
during RC6 exit.

v2: Add comment clarifying the WA (John H)
v3: Add more details to the comment (John H)

Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Reviewed-by: John Harrison <John.C.Harrison@Intel.com>
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240417054802.1766359-1-vinay.belgaumkar@intel.com
drivers/gpu/drm/xe/abi/guc_klvs_abi.h
drivers/gpu/drm/xe/xe_guc_ads.c
drivers/gpu/drm/xe/xe_wa_oob.rules

index 0972113f6b81ce36c7f7c8f679c225fe47a7e013..511cf974d585dd37d24091143f87bb742dc9ed6f 100644 (file)
@@ -326,6 +326,7 @@ enum xe_guc_klv_ids {
        GUC_WORKAROUND_KLV_BLOCK_INTERRUPTS_WHEN_MGSR_BLOCKED                           = 0x9002,
        GUC_WORKAROUND_KLV_ID_GAM_PFQ_SHADOW_TAIL_POLLING                               = 0x9005,
        GUC_WORKAROUND_KLV_ID_DISABLE_MTP_DURING_ASYNC_COMPUTE                          = 0x9007,
+       GUC_WA_KLV_NP_RD_WRITE_TO_CLEAR_RCSM_AT_CGP_LATE_RESTORE                        = 0x9008,
 };
 
 #endif
index 678ece36605605e5a025fa856a756849c482de44..1aafa486edec2f9abc773a7d932f68db41678b91 100644 (file)
@@ -282,6 +282,33 @@ static size_t calculate_golden_lrc_size(struct xe_guc_ads *ads)
        return total_size;
 }
 
+static void guc_waklv_enable_one_word(struct xe_guc_ads *ads,
+                                     enum xe_guc_klv_ids klv_id,
+                                     u32 value,
+                                     u32 *offset, u32 *remain)
+{
+       u32 size;
+       u32 klv_entry[] = {
+               /* 16:16 key/length */
+               FIELD_PREP(GUC_KLV_0_KEY, klv_id) |
+               FIELD_PREP(GUC_KLV_0_LEN, 1),
+               value,
+               /* 1 dword data */
+       };
+
+       size = sizeof(klv_entry);
+
+       if (*remain < size) {
+               drm_warn(&ads_to_xe(ads)->drm,
+                        "w/a klv buffer too small to add klv id %d\n", klv_id);
+       } else {
+               xe_map_memcpy_to(ads_to_xe(ads), ads_to_map(ads), *offset,
+                                klv_entry, size);
+               *offset += size;
+               *remain -= size;
+       }
+}
+
 static void guc_waklv_enable_simple(struct xe_guc_ads *ads,
                                    enum xe_guc_klv_ids klv_id, u32 *offset, u32 *remain)
 {
@@ -327,6 +354,17 @@ static void guc_waklv_init(struct xe_guc_ads *ads)
                                        GUC_WORKAROUND_KLV_ID_DISABLE_MTP_DURING_ASYNC_COMPUTE,
                                        &offset, &remain);
 
+       /*
+        * On RC6 exit, GuC will write register 0xB04 with the default value provided. As of now,
+        * the default value for this register is determined to be 0xC40. This could change in the
+        * future, so GuC depends on KMD to send it the correct value.
+        */
+       if (XE_WA(gt, 13011645652))
+               guc_waklv_enable_one_word(ads,
+                                         GUC_WA_KLV_NP_RD_WRITE_TO_CLEAR_RCSM_AT_CGP_LATE_RESTORE,
+                                         0xC40,
+                                         &offset, &remain);
+
        size = guc_ads_waklv_size(ads) - remain;
        if (!size)
                return;
index eb647d5a1e1626cf0b9bfc71336ae361cb25c145..12fe88796a497021def1f83e02531cfbde013f81 100644 (file)
@@ -26,3 +26,4 @@
                MEDIA_VERSION(2000)
 16022287689    GRAPHICS_VERSION(2001)
                GRAPHICS_VERSION(2004)
+13011645652    GRAPHICS_VERSION(2004)