[PATCH v2 1/3] drm/xe/guc: move KLV helpers to common file

Daniele Ceraolo Spurio daniele.ceraolospurio at intel.com
Thu Mar 6 00:57:43 UTC 2025


The GuC uses the same format for all its KLVs, so having the functions
to set them in a common file will allow us to re-use it for different
types of KLVs and not just the WAs in ADS.
The functions have also been reworked to avoid duplication and moved to
using dword aligned offsets and sizes to match other functions in the same
file.

The next patch will make use of these functions for a new H2G command.

v2: further rework code to have a single generic emission function, rename
helpers (Michal)

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
Cc: John Harrison <John.C.Harrison at Intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko at intel.com>
---
 drivers/gpu/drm/xe/xe_guc_ads.c         | 89 ++++++-------------------
 drivers/gpu/drm/xe/xe_guc_klv_helpers.c | 45 +++++++++++++
 drivers/gpu/drm/xe/xe_guc_klv_helpers.h | 19 ++++++
 3 files changed, 84 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c
index e7c9e095a19f..ec507d25ec72 100644
--- a/drivers/gpu/drm/xe/xe_guc_ads.c
+++ b/drivers/gpu/drm/xe/xe_guc_ads.c
@@ -22,6 +22,7 @@
 #include "xe_guc.h"
 #include "xe_guc_capture.h"
 #include "xe_guc_ct.h"
+#include "xe_guc_klv_helpers.h"
 #include "xe_hw_engine.h"
 #include "xe_lrc.h"
 #include "xe_map.h"
@@ -283,56 +284,6 @@ 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)
-{
-	u32 klv_entry[] = {
-		/* 16:16 key/length */
-		FIELD_PREP(GUC_KLV_0_KEY, klv_id) |
-		FIELD_PREP(GUC_KLV_0_LEN, 0),
-		/* 0 dwords data */
-	};
-	u32 size;
-
-	size = sizeof(klv_entry);
-
-	if (xe_gt_WARN(ads_to_gt(ads), *remain < size,
-		       "w/a klv buffer too small to add klv id %d\n", klv_id))
-		return;
-
-	xe_map_memcpy_to(ads_to_xe(ads), ads_to_map(ads), *offset,
-			 klv_entry, size);
-	*offset += size;
-	*remain -= size;
-}
-
 static void guc_waklv_init(struct xe_guc_ads *ads)
 {
 	struct xe_gt *gt = ads_to_gt(ads);
@@ -343,22 +294,22 @@ static void guc_waklv_init(struct xe_guc_ads *ads)
 	remain = guc_ads_waklv_size(ads);
 
 	if (XE_WA(gt, 14019882105) || XE_WA(gt, 16021333562))
-		guc_waklv_enable_simple(ads,
-					GUC_WORKAROUND_KLV_BLOCK_INTERRUPTS_WHEN_MGSR_BLOCKED,
-					&offset, &remain);
+		xe_guc_klv_emit_nodata(ads_to_guc(ads), ads_to_map(ads),
+				       GUC_WORKAROUND_KLV_BLOCK_INTERRUPTS_WHEN_MGSR_BLOCKED,
+				       &offset, &remain);
 	if (XE_WA(gt, 18024947630))
-		guc_waklv_enable_simple(ads,
-					GUC_WORKAROUND_KLV_ID_GAM_PFQ_SHADOW_TAIL_POLLING,
-					&offset, &remain);
+		xe_guc_klv_emit_nodata(ads_to_guc(ads), ads_to_map(ads),
+				       GUC_WORKAROUND_KLV_ID_GAM_PFQ_SHADOW_TAIL_POLLING,
+				       &offset, &remain);
 	if (XE_WA(gt, 16022287689))
-		guc_waklv_enable_simple(ads,
-					GUC_WORKAROUND_KLV_ID_DISABLE_MTP_DURING_ASYNC_COMPUTE,
-					&offset, &remain);
+		xe_guc_klv_emit_nodata(ads_to_guc(ads), ads_to_map(ads),
+				       GUC_WORKAROUND_KLV_ID_DISABLE_MTP_DURING_ASYNC_COMPUTE,
+				       &offset, &remain);
 
 	if (XE_WA(gt, 14022866841))
-		guc_waklv_enable_simple(ads,
-					GUC_WA_KLV_WAKE_POWER_DOMAINS_FOR_OUTBOUND_MMIO,
-					&offset, &remain);
+		xe_guc_klv_emit_nodata(ads_to_guc(ads), ads_to_map(ads),
+				       GUC_WA_KLV_WAKE_POWER_DOMAINS_FOR_OUTBOUND_MMIO,
+				       &offset, &remain);
 
 	/*
 	 * On RC6 exit, GuC will write register 0xB04 with the default value provided. As of now,
@@ -366,15 +317,15 @@ static void guc_waklv_init(struct xe_guc_ads *ads)
 	 * 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);
+		xe_guc_klv_emit_one_word(ads_to_guc(ads), ads_to_map(ads),
+					 GUC_WA_KLV_NP_RD_WRITE_TO_CLEAR_RCSM_AT_CGP_LATE_RESTORE,
+					 0xC40,
+					 &offset, &remain);
 
 	if (XE_WA(gt, 14022293748) || XE_WA(gt, 22019794406))
-		guc_waklv_enable_simple(ads,
-					GUC_WORKAROUND_KLV_ID_BACK_TO_BACK_RCS_ENGINE_RESET,
-					&offset, &remain);
+		xe_guc_klv_emit_nodata(ads_to_guc(ads), ads_to_map(ads),
+				       GUC_WORKAROUND_KLV_ID_BACK_TO_BACK_RCS_ENGINE_RESET,
+				       &offset, &remain);
 
 	size = guc_ads_waklv_size(ads) - remain;
 	if (!size)
diff --git a/drivers/gpu/drm/xe/xe_guc_klv_helpers.c b/drivers/gpu/drm/xe/xe_guc_klv_helpers.c
index 146a6eda9e06..74379c359d45 100644
--- a/drivers/gpu/drm/xe/xe_guc_klv_helpers.c
+++ b/drivers/gpu/drm/xe/xe_guc_klv_helpers.c
@@ -7,8 +7,11 @@
 #include <drm/drm_print.h>
 
 #include "abi/guc_klvs_abi.h"
+#include "xe_gt_printk.h"
+#include "xe_guc.h"
 #include "xe_guc_klv_helpers.h"
 #include "xe_guc_klv_thresholds_set.h"
+#include "xe_map.h"
 
 #define make_u64(hi, lo) ((u64)((u64)(u32)(hi) << 32 | (u32)(lo)))
 
@@ -146,3 +149,45 @@ int xe_guc_klv_count(const u32 *klvs, u32 num_dwords)
 
 	return num_dwords ? -ENODATA : num_klvs;
 }
+
+static void __klv_emit(struct xe_device *xe, struct iosys_map *map,
+		       u32 *data, u32 size, u32 *offset, u32 *remain)
+{
+	xe_map_memcpy_to(xe, map, *offset, data, size);
+	*offset += size;
+	*remain -= size;
+}
+
+/**
+ * xe_guc_klv_emit - Emits a KLV to an iosys mapped buffer
+ * @guc: the guc structure
+ * @map: the iosys_map to write to
+ * @key: the KLV to enable
+ * @data: pointer to the data for the KLV (can be NULL)
+ * @data_size: size of the data for the KLV (MBZ if data is NULL)
+ * @offset: pointer to a variable holding the offset to write to
+ * @remain: pointer to a variable holding the available writing space
+ *
+ * The function checks if there is enough space to emit the KLV and if so
+ * writes it to memory. After the write, the offset and remain variables
+ * are respectively increased and decreased of the written size to be ready for
+ * the next emission.
+ */
+void xe_guc_klv_emit(struct xe_guc *guc, struct iosys_map *map, u16 key,
+		     void *data, u32 data_size, u32 *offset, u32 *remain)
+{
+	struct xe_device *xe = guc_to_xe(guc);
+	u32 klv_entry = PREP_GUC_KLV(key, data_size / sizeof(u32));
+
+	/* GuC expects an array of u32s */
+	xe_assert(guc_to_xe(guc), !(data_size % sizeof(u32)));
+
+	if (xe_gt_WARN(guc_to_gt(guc), *remain < (sizeof(klv_entry) + data_size),
+		       "KLV buffer too small to add klv id 0x%04x\n", key))
+		return;
+
+	__klv_emit(xe, map, &klv_entry, sizeof(klv_entry), offset, remain);
+
+	if (data_size)
+		__klv_emit(xe, map, data, data_size, offset, remain);
+}
diff --git a/drivers/gpu/drm/xe/xe_guc_klv_helpers.h b/drivers/gpu/drm/xe/xe_guc_klv_helpers.h
index c676d21c173b..72b33e5019de 100644
--- a/drivers/gpu/drm/xe/xe_guc_klv_helpers.h
+++ b/drivers/gpu/drm/xe/xe_guc_klv_helpers.h
@@ -10,6 +10,8 @@
 #include <linux/types.h>
 
 struct drm_printer;
+struct iosys_map;
+struct xe_guc;
 
 const char *xe_guc_klv_key_to_string(u16 key);
 
@@ -61,4 +63,21 @@ int xe_guc_klv_count(const u32 *klvs, u32 num_dwords);
 #define PREP_GUC_KLV_TAG(TAG) \
 	PREP_GUC_KLV_CONST(MAKE_GUC_KLV_KEY(TAG), MAKE_GUC_KLV_LEN(TAG))
 
+void xe_guc_klv_emit(struct xe_guc *guc, struct iosys_map *map, u16 key,
+		     void *data, u32 data_size, u32 *offset, u32 *remain);
+
+static inline void
+xe_guc_klv_emit_nodata(struct xe_guc *guc, struct iosys_map *map,
+		       u16 key, u32 *offset, u32 *remain)
+{
+	return xe_guc_klv_emit(guc, map, key, NULL, 0, offset, remain);
+}
+
+static inline void
+xe_guc_klv_emit_one_word(struct xe_guc *guc, struct iosys_map *map,
+			 u16 key, u32 value, u32 *offset, u32 *remain)
+{
+	return xe_guc_klv_emit(guc, map, key, &value, sizeof(u32), offset, remain);
+}
+
 #endif
-- 
2.43.0



More information about the Intel-xe mailing list