[PATCH i-g-t 5/5] lib/xe/xe_sriov_provisioning: Extract function to search provisioned PTE ranges

Marcin Bernatowicz marcin.bernatowicz at linux.intel.com
Wed Oct 30 19:36:29 UTC 2024


Extract the function to search for GGTT provisioned PTE ranges for each VF
from test/xe_sriov_flr to a library file lib/xe/xe_sriov_provisioning.
This refactoring improves code reusability and will allow to prepare a
test comparing debugfs exposed ggtt_provisioned attribute.

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz at linux.intel.com>
Cc: Adam Miszczak <adam.miszczak at linux.intel.com>
Cc: C V Narasimha <narasimha.c.v at intel.com>
Cc: Jakub Kolakowski <jakub1.kolakowski at intel.com>
Cc: K V P Satyanarayana <satyanarayana.k.v.p at intel.com>
Cc: Lukasz Laguna <lukasz.laguna at intel.com>
Cc: Michał Wajdeczko <michal.wajdeczko at intel.com>
Cc: Michał Winiarski <michal.winiarski at intel.com>
Cc: Piotr Piórkowski <piotr.piorkowski at intel.com>
Cc: Tomasz Lis <tomasz.lis at intel.com>
---
 lib/xe/xe_sriov_provisioning.c |  91 +++++++++++++++++++++++
 lib/xe/xe_sriov_provisioning.h |   5 ++
 tests/intel/xe_sriov_flr.c     | 130 +++++++++++----------------------
 3 files changed, 137 insertions(+), 89 deletions(-)

diff --git a/lib/xe/xe_sriov_provisioning.c b/lib/xe/xe_sriov_provisioning.c
index 6a9ad411a..cbd6a49b6 100644
--- a/lib/xe/xe_sriov_provisioning.c
+++ b/lib/xe/xe_sriov_provisioning.c
@@ -5,6 +5,10 @@
 
 #include <stdlib.h>
 
+#include "igt_core.h"
+#include "intel_chipset.h"
+#include "linux_scaffold.h"
+#include "xe/xe_mmio.h"
 #include "xe/xe_sriov_provisioning.h"
 
 /**
@@ -31,3 +35,90 @@ const char *xe_sriov_shared_res_to_string(enum xe_sriov_shared_res res)
 
 	return NULL;
 }
+
+#define PRE_1250_IP_VER_GGTT_PTE_VFID_MASK	GENMASK_ULL(4, 2)
+#define GGTT_PTE_VFID_MASK			GENMASK_ULL(11, 2)
+#define GGTT_PTE_VFID_SHIFT			2
+
+static uint64_t get_vfid_mask(int fd)
+{
+	uint16_t dev_id = intel_get_drm_devid(fd);
+
+	return (intel_graphics_ver(dev_id) >= IP_VER(12, 50)) ?
+		GGTT_PTE_VFID_MASK : PRE_1250_IP_VER_GGTT_PTE_VFID_MASK;
+}
+
+/**
+ * xe_sriov_find_ggtt_provisioned_pte_offsets - Find GGTT provisioned PTE offsets
+ * @pf_fd: File descriptor for the Physical Function
+ * @gt: GT identifier
+ * @mmio: Pointer to the MMIO structure
+ * @ranges: Pointer to the array of provisioned ranges
+ * @nr_ranges: Pointer to the number of provisioned ranges
+ *
+ * This function searches for GGTT provisioned PTE ranges for each VF and
+ * populates the provided ranges array with the start and end offsets of
+ * each range. The number of ranges found is stored in nr_ranges.
+ *
+ * The function reads the GGTT PTEs and identifies the VF ID associated with
+ * each PTE. It then groups contiguous PTEs with the same VF ID into ranges.
+ * The ranges are dynamically allocated and must be freed by the caller.
+ * The start and end offsets in each range are inclusive.
+ *
+ * Returns 0 on success, or a negative error code on failure.
+ */
+int xe_sriov_find_ggtt_provisioned_pte_offsets(int pf_fd, int gt, struct xe_mmio *mmio,
+					       struct xe_sriov_provisioned_range **ranges,
+					       unsigned int *nr_ranges)
+{
+	uint64_t vfid_mask = get_vfid_mask(pf_fd);
+	unsigned int vf_id, current_vf_id = -1;
+	uint32_t current_start = 0;
+	uint32_t current_end = 0;
+	xe_ggtt_pte_t pte;
+
+	*ranges = NULL;
+	*nr_ranges = 0;
+
+	for (uint32_t offset = 0; offset < SZ_8M; offset += sizeof(xe_ggtt_pte_t)) {
+		pte = xe_mmio_ggtt_read(mmio, gt, offset);
+		vf_id = (pte & vfid_mask) >> GGTT_PTE_VFID_SHIFT;
+
+		if (vf_id != current_vf_id) {
+			if (current_vf_id != -1) {
+				/* End the current range */
+				*ranges = realloc(*ranges, (*nr_ranges + 1) *
+						  sizeof(struct xe_sriov_provisioned_range));
+				igt_assert(*ranges);
+				igt_debug("Found VF%u ggtt range [%#x-%#x] num_ptes=%ld\n",
+					  current_vf_id, current_start, current_end,
+					  (current_end - current_start + sizeof(xe_ggtt_pte_t)) /
+					  sizeof(xe_ggtt_pte_t));
+				(*ranges)[*nr_ranges].vf_id = current_vf_id;
+				(*ranges)[*nr_ranges].start = current_start;
+				(*ranges)[*nr_ranges].end = current_end;
+				(*nr_ranges)++;
+			}
+			/* Start a new range */
+			current_vf_id = vf_id;
+			current_start = offset;
+		}
+		current_end = offset;
+	}
+
+	if (current_vf_id != -1) {
+		*ranges = realloc(*ranges, (*nr_ranges + 1) *
+				  sizeof(struct xe_sriov_provisioned_range));
+		igt_assert(*ranges);
+		igt_debug("Found VF%u ggtt range [%#x-%#x] num_ptes=%ld\n",
+			  current_vf_id, current_start, current_end,
+			  (current_end - current_start + sizeof(xe_ggtt_pte_t)) /
+			  sizeof(xe_ggtt_pte_t));
+		(*ranges)[*nr_ranges].vf_id = current_vf_id;
+		(*ranges)[*nr_ranges].start = current_start;
+		(*ranges)[*nr_ranges].end = current_end;
+		(*nr_ranges)++;
+	}
+
+	return 0;
+}
diff --git a/lib/xe/xe_sriov_provisioning.h b/lib/xe/xe_sriov_provisioning.h
index 7b7b3db90..aa2f08f52 100644
--- a/lib/xe/xe_sriov_provisioning.h
+++ b/lib/xe/xe_sriov_provisioning.h
@@ -8,6 +8,8 @@
 
 #include <stdint.h>
 
+struct xe_mmio;
+
 /**
  * enum xe_sriov_shared_res - Shared resource types
  * @XE_SRIOV_SHARED_RES_CONTEXTS: Contexts
@@ -41,5 +43,8 @@ struct xe_sriov_provisioned_range {
 };
 
 const char *xe_sriov_shared_res_to_string(enum xe_sriov_shared_res res);
+int xe_sriov_find_ggtt_provisioned_pte_offsets(int pf_fd, int gt, struct xe_mmio *mmio,
+					       struct xe_sriov_provisioned_range **ranges,
+					       unsigned int *nr_ranges);
 
 #endif /* __XE_SRIOV_PROVISIONING_H__ */
diff --git a/tests/intel/xe_sriov_flr.c b/tests/intel/xe_sriov_flr.c
index f698eaf3d..1049cffec 100644
--- a/tests/intel/xe_sriov_flr.c
+++ b/tests/intel/xe_sriov_flr.c
@@ -299,14 +299,6 @@ disable_vfs:
 #define GEN12_VF_CAP_REG			0x1901f8
 #define GGTT_PTE_TEST_FIELD_MASK		GENMASK_ULL(19, 12)
 #define GGTT_PTE_ADDR_SHIFT			12
-#define PRE_1250_IP_VER_GGTT_PTE_VFID_MASK	GENMASK_ULL(4, 2)
-#define GGTT_PTE_VFID_MASK			GENMASK_ULL(11, 2)
-#define GGTT_PTE_VFID_SHIFT			2
-
-#define for_each_pte_offset(pte_offset__, ggtt_offset_range__) \
-	for ((pte_offset__) = ((ggtt_offset_range__)->begin);  \
-	     (pte_offset__) < ((ggtt_offset_range__)->end);    \
-	     (pte_offset__) += sizeof(xe_ggtt_pte_t))
 
 struct ggtt_ops {
 	void (*set_pte)(struct xe_mmio *mmio, int gt, uint32_t pte_offset, xe_ggtt_pte_t pte);
@@ -314,10 +306,15 @@ struct ggtt_ops {
 };
 
 struct ggtt_provisioned_offset_range {
-	uint32_t begin;
+	uint32_t start;
 	uint32_t end;
 };
 
+#define for_each_pte_offset(pte_offset__, ggtt_offset_range__) \
+	for ((pte_offset__) = ((ggtt_offset_range__)->start);  \
+	     (pte_offset__) <= ((ggtt_offset_range__)->end);   \
+	     (pte_offset__) += sizeof(xe_ggtt_pte_t))
+
 struct ggtt_data {
 	struct subcheck_data base;
 	struct ggtt_provisioned_offset_range *pte_offsets;
@@ -373,98 +370,53 @@ static bool is_intel_mmio_initialized(const struct intel_mmio_data *mmio)
 	return mmio->dev;
 }
 
-static uint64_t get_vfid_mask(int pf_fd)
-{
-	uint16_t dev_id = intel_get_drm_devid(pf_fd);
-
-	return (intel_graphics_ver(dev_id) >= IP_VER(12, 50)) ?
-		GGTT_PTE_VFID_MASK : PRE_1250_IP_VER_GGTT_PTE_VFID_MASK;
-}
-
-static bool pte_contains_vfid(const xe_ggtt_pte_t pte, const unsigned int vf_id,
-			      const uint64_t vfid_mask)
-{
-	return ((pte & vfid_mask) >> GGTT_PTE_VFID_SHIFT) == vf_id;
-}
-
-static bool is_offset_in_range(uint32_t offset,
-			       const struct ggtt_provisioned_offset_range *ranges,
-			       size_t num_ranges)
-{
-	for (size_t i = 0; i < num_ranges; i++)
-		if (offset >= ranges[i].begin && offset < ranges[i].end)
-			return true;
-
-	return false;
-}
-
-static void find_ggtt_provisioned_ranges(struct ggtt_data *gdata)
+static int populate_ggtt_pte_offsets(struct ggtt_data *gdata)
 {
-	uint32_t limit = gdata->mmio->intel_mmio.mmio_size - SZ_8M > SZ_8M ?
-				 SZ_8M :
-				 gdata->mmio->intel_mmio.mmio_size - SZ_8M;
-	uint64_t vfid_mask = get_vfid_mask(gdata->base.pf_fd);
-	xe_ggtt_pte_t pte;
+	int ret, pf_fd = gdata->base.pf_fd, num_vfs = gdata->base.num_vfs;
+	struct xe_sriov_provisioned_range *ranges;
+	unsigned int nr_ranges, gt = gdata->base.gt;
 
-	gdata->pte_offsets = calloc(gdata->base.num_vfs + 1, sizeof(*gdata->pte_offsets));
+	gdata->pte_offsets = calloc(num_vfs + 1, sizeof(*gdata->pte_offsets));
 	igt_assert(gdata->pte_offsets);
 
-	for (int vf_id = 1; vf_id <= gdata->base.num_vfs; vf_id++) {
-		uint32_t range_begin = 0;
-		int adjacent = 0;
-		int num_ranges = 0;
-
-		for (uint32_t offset = 0; offset < limit; offset += sizeof(xe_ggtt_pte_t)) {
-			/* Skip already found ranges */
-			if (is_offset_in_range(offset, gdata->pte_offsets, vf_id))
-				continue;
-
-			pte = xe_mmio_ggtt_read(gdata->mmio, gdata->base.gt, offset);
-
-			if (pte_contains_vfid(pte, vf_id, vfid_mask)) {
-				if (adjacent == 0)
-					range_begin = offset;
+	ret = xe_sriov_find_ggtt_provisioned_pte_offsets(pf_fd, gt, gdata->mmio,
+							 &ranges, &nr_ranges);
+	if (ret) {
+		set_skip_reason(&gdata->base, "Failed to scan GGTT PTE offset ranges on gt%u (%d)\n",
+				gt, ret);
+		return -1;
+	}
 
-				adjacent++;
-			} else if (adjacent > 0) {
-				uint32_t range_end = range_begin +
-						     adjacent * sizeof(xe_ggtt_pte_t);
+	for (unsigned int i = 0; i < nr_ranges; ++i) {
+		const unsigned int vf_id = ranges[i].vf_id;
 
-				igt_debug("Found VF%d ggtt range begin=%#x end=%#x num_ptes=%d\n",
-					  vf_id, range_begin, range_end, adjacent);
+		if (vf_id == 0)
+			continue;
 
-				if (adjacent > gdata->pte_offsets[vf_id].end -
-					       gdata->pte_offsets[vf_id].begin) {
-					gdata->pte_offsets[vf_id].begin = range_begin;
-					gdata->pte_offsets[vf_id].end = range_end;
-				}
+		igt_assert(vf_id >= 1 && vf_id <= num_vfs);
 
-				adjacent = 0;
-				num_ranges++;
-			}
+		if (gdata->pte_offsets[vf_id].end) {
+			set_skip_reason(&gdata->base, "Duplicate GGTT PTE offset range for VF%u\n",
+					vf_id);
+			free(ranges);
+			return -1;
 		}
 
-		if (adjacent > 0) {
-			uint32_t range_end = range_begin + adjacent * sizeof(xe_ggtt_pte_t);
-
-			igt_debug("Found VF%d ggtt range begin=%#x end=%#x num_ptes=%d\n",
-				  vf_id, range_begin, range_end, adjacent);
+		gdata->pte_offsets[vf_id].start = ranges[i].start;
+		gdata->pte_offsets[vf_id].end = ranges[i].end;
+	}
 
-			if (adjacent > gdata->pte_offsets[vf_id].end -
-				       gdata->pte_offsets[vf_id].begin) {
-				gdata->pte_offsets[vf_id].begin = range_begin;
-				gdata->pte_offsets[vf_id].end = range_end;
-			}
-			num_ranges++;
-		}
+	free(ranges);
 
-		if (num_ranges == 0) {
+	for (int vf_id = 1; vf_id <= num_vfs; ++vf_id)
+		if (!gdata->pte_offsets[vf_id].end) {
 			set_fail_reason(&gdata->base,
-					"Failed to find VF%d provisioned ggtt range\n", vf_id);
-			return;
+					"Failed to find VF%u provisioned GGTT PTE offset range\n",
+					vf_id);
+			return -1;
 		}
-		igt_warn_on_f(num_ranges > 1, "Found %d ranges for VF%d\n", num_ranges, vf_id);
-	}
+
+	return 0;
 }
 
 static void ggtt_subcheck_init(struct subcheck_data *data)
@@ -486,7 +438,7 @@ static void ggtt_subcheck_init(struct subcheck_data *data)
 		if (!is_intel_mmio_initialized(&gdata->mmio->intel_mmio))
 			xe_mmio_vf_access_init(data->pf_fd, 0 /*PF*/, gdata->mmio);
 
-		find_ggtt_provisioned_ranges(gdata);
+		populate_ggtt_pte_offsets(gdata);
 	} else {
 		set_fail_reason(data, "xe_mmio is NULL\n");
 	}
@@ -502,7 +454,7 @@ static void ggtt_subcheck_prepare_vf(int vf_id, struct subcheck_data *data)
 		return;
 
 	igt_debug("Prepare gpa on VF%u offset range [%#x-%#x]\n", vf_id,
-		  gdata->pte_offsets[vf_id].begin,
+		  gdata->pte_offsets[vf_id].start,
 		  gdata->pte_offsets[vf_id].end);
 
 	for_each_pte_offset(pte_offset, &gdata->pte_offsets[vf_id]) {
-- 
2.31.1



More information about the igt-dev mailing list