drm/i915/guc: Add support for w/a KLVs
authorJohn Harrison <John.C.Harrison@Intel.com>
Fri, 23 Feb 2024 20:56:31 +0000 (12:56 -0800)
committerJohn Harrison <John.C.Harrison@Intel.com>
Thu, 7 Mar 2024 23:26:45 +0000 (15:26 -0800)
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 <John.C.Harrison@Intel.com>
Reviewed-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240223205632.1621019-3-John.C.Harrison@Intel.com
drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h
drivers/gpu/drm/i915/gt/uc/intel_guc.h
drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c
drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h

index dabeaf4..00d6402 100644 (file)
@@ -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,
index 813cc88..b572fc1 100644 (file)
@@ -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 */
index af63973..e0312f7 100644 (file)
  *      +---------------------------------------+
  *      | 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 @@ engine_instance_list:
        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(&gt->uc))
+               return;
+
+       if (GUC_FIRMWARE_VER(guc) < MAKE_GUC_VER(70, 10, 0))
+               return;
+
+       GEM_BUG_ON(iosys_map_is_null(&guc->ads_map));
+       offset = guc_ads_waklv_offset(guc);
+       remain = guc_ads_waklv_size(guc);
+
+       /*
+        * Add workarounds here:
+        *
+        * if (want_wa_<name>) {
+        *      size = guc_waklv_<name>(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: */
+       return PAGE_SIZE;
+}
+
 static void __guc_ads_init(struct intel_guc *guc)
 {
        struct intel_gt *gt = guc_to_gt(guc);
@@ -843,6 +905,9 @@ static void __guc_ads_init(struct intel_guc *guc)
        /* MMIO save/restore list */
        guc_mmio_reg_state_init(guc);
 
+       /* Workaround KLV list */
+       guc_waklv_init(guc);
+
        /* Private Data */
        ads_blob_write(guc, ads.private_data, base +
                       guc_ads_private_data_offset(guc));
@@ -886,6 +951,12 @@ int intel_guc_ads_create(struct intel_guc *guc)
                return ret;
        guc->ads_capture_size = ret;
 
+       /* And don't forget the workaround KLVs: */
+       ret = guc_prep_waklv(guc);
+       if (ret < 0)
+               return ret;
+       guc->ads_waklv_size = ret;
+
        /* Now the total size can be determined: */
        size = guc_ads_blob_size(guc);
 
index 52332bb..0a37c42 100644 (file)
@@ -115,6 +115,7 @@ static inline bool guc_load_done(struct intel_uncore *uncore, u32 *status, bool
        case INTEL_GUC_LOAD_STATUS_INIT_DATA_INVALID:
        case INTEL_GUC_LOAD_STATUS_MPU_DATA_INVALID:
        case INTEL_GUC_LOAD_STATUS_INIT_MMIO_SAVE_RESTORE_INVALID:
+       case INTEL_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR:
                *success = false;
                return true;
        }
@@ -241,6 +242,11 @@ static int guc_wait_ucode(struct intel_guc *guc)
                        ret = -EPERM;
                        break;
 
+               case INTEL_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR:
+                       guc_info(guc, "invalid w/a KLV entry\n");
+                       ret = -EINVAL;
+                       break;
+
                case INTEL_GUC_LOAD_STATUS_HWCONFIG_START:
                        guc_info(guc, "still extracting hwconfig table.\n");
                        ret = -ETIMEDOUT;
index 4886318..14797e8 100644 (file)
@@ -431,7 +431,10 @@ struct guc_ads {
        u32 capture_instance[GUC_CAPTURE_LIST_INDEX_MAX][GUC_MAX_ENGINE_CLASSES];
        u32 capture_class[GUC_CAPTURE_LIST_INDEX_MAX][GUC_MAX_ENGINE_CLASSES];
        u32 capture_global[GUC_CAPTURE_LIST_INDEX_MAX];
-       u32 reserved[14];
+       u32 wa_klv_addr_lo;
+       u32 wa_klv_addr_hi;
+       u32 wa_klv_size;
+       u32 reserved[11];
 } __packed;
 
 /* Engine usage stats */