[PATCH i-g-t 5/5] lib/xe/xe_sriov_provisioning: Extract function to search provisioned PTE ranges
Adam Miszczak
adam.miszczak at linux.intel.com
Wed Nov 6 08:08:01 UTC 2024
On 30.10.2024 20:36, Marcin Bernatowicz wrote:
> 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
Nit: "This function" seems redundant. I suggest to align with an other
descriptions, that start with just a verb.
> + * 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
Ditto.
> + * 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]) {
In general LGTM,
Reviewed-by: Adam Miszczak <adam.miszczak at linux.intel.com>
More information about the igt-dev
mailing list