Commit eb9b3473 authored by Michal Wajdeczko's avatar Michal Wajdeczko
Browse files

drm/xe/vf: Move tile-related VF functions to separate file



Some of our VF functions, even if they take a GT pointer, work
only on primary GT and really are tile-related and would be better
to keep them separate from the rest of true GT-oriented functions.
Move them to a file and update to take a tile pointer instead.

Signed-off-by: default avatarMichal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Tomasz Lis <tomasz.lis@intel.com>
Reviewed-by: default avatarTomasz Lis <tomasz.lis@intel.com>
Link: https://lore.kernel.org/r/20250602103325.549-3-michal.wajdeczko@intel.com
parent ce2ae1b9
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -139,7 +139,8 @@ xe-y += \
	xe_guc_relay.o \
	xe_memirq.o \
	xe_sriov.o \
	xe_sriov_vf.o
	xe_sriov_vf.o \
	xe_tile_sriov_vf.o

xe-$(CONFIG_PCI_IOV) += \
	xe_gt_sriov_pf.o \
+2 −2
Original line number Diff line number Diff line
@@ -22,12 +22,12 @@
#include "xe_device.h"
#include "xe_gt.h"
#include "xe_gt_printk.h"
#include "xe_gt_sriov_vf.h"
#include "xe_gt_tlb_invalidation.h"
#include "xe_map.h"
#include "xe_mmio.h"
#include "xe_pm.h"
#include "xe_sriov.h"
#include "xe_tile_sriov_vf.h"
#include "xe_wa.h"
#include "xe_wopcm.h"

@@ -258,7 +258,7 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt)
		return err;

	if (IS_SRIOV_VF(xe)) {
		err = xe_gt_sriov_vf_prepare_ggtt(xe_tile_get_gt(ggtt->tile, 0));
		err = xe_tile_sriov_vf_prepare_ggtt(ggtt->tile);
		if (err)
			return err;
	}
+0 −245
Original line number Diff line number Diff line
@@ -613,168 +613,6 @@ s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt)
	return config->ggtt_shift;
}

static int vf_init_ggtt_balloons(struct xe_gt *gt)
{
	struct xe_tile *tile = gt_to_tile(gt);
	struct xe_ggtt *ggtt = tile->mem.ggtt;

	xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt)));
	xe_gt_assert(gt, !xe_gt_is_media_type(gt));

	tile->sriov.vf.ggtt_balloon[0] = xe_ggtt_node_init(ggtt);
	if (IS_ERR(tile->sriov.vf.ggtt_balloon[0]))
		return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]);

	tile->sriov.vf.ggtt_balloon[1] = xe_ggtt_node_init(ggtt);
	if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) {
		xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]);
		return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]);
	}

	return 0;
}

/**
 * xe_gt_sriov_vf_balloon_ggtt_locked - Insert balloon nodes to limit used GGTT address range.
 * @gt: the &xe_gt struct instance
 * Return: 0 on success or a negative error code on failure.
 */
int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt)
{
	struct xe_gt_sriov_vf_selfconfig *config = &gt->sriov.vf.self_config;
	struct xe_tile *tile = gt_to_tile(gt);
	struct xe_device *xe = gt_to_xe(gt);
	u64 start, end;
	int err;

	xe_gt_assert(gt, IS_SRIOV_VF(xe));
	xe_gt_assert(gt, !xe_gt_is_media_type(gt));
	lockdep_assert_held(&tile->mem.ggtt->lock);

	if (!config->ggtt_size)
		return -ENODATA;

	/*
	 * VF can only use part of the GGTT as allocated by the PF:
	 *
	 *      WOPCM                                  GUC_GGTT_TOP
	 *      |<------------ Total GGTT size ------------------>|
	 *
	 *           VF GGTT base -->|<- size ->|
	 *
	 *      +--------------------+----------+-----------------+
	 *      |////////////////////|   block  |\\\\\\\\\\\\\\\\\|
	 *      +--------------------+----------+-----------------+
	 *
	 *      |<--- balloon[0] --->|<-- VF -->|<-- balloon[1] ->|
	 */

	start = xe_wopcm_size(xe);
	end = config->ggtt_base;
	if (end != start) {
		err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[0],
							 start, end);
		if (err)
			return err;
	}

	start = config->ggtt_base + config->ggtt_size;
	end = GUC_GGTT_TOP;
	if (end != start) {
		err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[1],
							 start, end);
		if (err) {
			xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]);
			return err;
		}
	}

	return 0;
}

static int vf_balloon_ggtt(struct xe_gt *gt)
{
	struct xe_ggtt *ggtt = gt_to_tile(gt)->mem.ggtt;
	int err;

	mutex_lock(&ggtt->lock);
	err = xe_gt_sriov_vf_balloon_ggtt_locked(gt);
	mutex_unlock(&ggtt->lock);

	return err;
}

/**
 * xe_gt_sriov_vf_deballoon_ggtt_locked - Remove balloon nodes.
 * @gt: the &xe_gt struct instance
 */
void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt)
{
	struct xe_tile *tile = gt_to_tile(gt);

	xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile)));
	xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[1]);
	xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]);
}

static void vf_deballoon_ggtt(struct xe_gt *gt)
{
	struct xe_tile *tile = gt_to_tile(gt);

	mutex_lock(&tile->mem.ggtt->lock);
	xe_gt_sriov_vf_deballoon_ggtt_locked(gt);
	mutex_unlock(&tile->mem.ggtt->lock);
}

static void vf_fini_ggtt_balloons(struct xe_gt *gt)
{
	struct xe_tile *tile = gt_to_tile(gt);

	xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt)));
	xe_gt_assert(gt, !xe_gt_is_media_type(gt));

	xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[1]);
	xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]);
}

static void cleanup_ggtt(struct drm_device *drm, void *arg)
{
	struct xe_gt *gt = arg;

	vf_deballoon_ggtt(gt);
	vf_fini_ggtt_balloons(gt);
}

/**
 * xe_gt_sriov_vf_prepare_ggtt - Prepare a VF's GGTT configuration.
 * @gt: the &xe_gt
 *
 * This function is for VF use only.
 *
 * Return: 0 on success or a negative error code on failure.
 */
int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt)
{
	struct xe_tile *tile = gt_to_tile(gt);
	struct xe_device *xe = tile_to_xe(tile);
	int err;

	if (xe_gt_is_media_type(gt))
		return 0;

	err = vf_init_ggtt_balloons(gt);
	if (err)
		return err;

	err = vf_balloon_ggtt(gt);
	if (err) {
		vf_fini_ggtt_balloons(gt);
		return err;
	}

	return drmm_add_action_or_reset(&xe->drm, cleanup_ggtt, gt);
}

static int relay_action_handshake(struct xe_gt *gt, u32 *major, u32 *minor)
{
	u32 request[VF2PF_HANDSHAKE_REQUEST_MSG_LEN] = {
@@ -870,89 +708,6 @@ int xe_gt_sriov_vf_connect(struct xe_gt *gt)
	return err;
}

/**
 * DOC: GGTT nodes shifting during VF post-migration recovery
 *
 * The first fixup applied to the VF KMD structures as part of post-migration
 * recovery is shifting nodes within &xe_ggtt instance. The nodes are moved
 * from range previously assigned to this VF, into newly provisioned area.
 * The changes include balloons, which are resized accordingly.
 *
 * The balloon nodes are there to eliminate unavailable ranges from use: one
 * reserves the GGTT area below the range for current VF, and another one
 * reserves area above.
 *
 * Below is a GGTT layout of example VF, with a certain address range assigned to
 * said VF, and inaccessible areas above and below:
 *
 *  0                                                                        4GiB
 *  |<--------------------------- Total GGTT size ----------------------------->|
 *      WOPCM                                                         GUC_TOP
 *      |<-------------- Area mappable by xe_ggtt instance ---------------->|
 *
 *  +---+---------------------------------+----------+----------------------+---+
 *  |\\\|/////////////////////////////////|  VF mem  |//////////////////////|\\\|
 *  +---+---------------------------------+----------+----------------------+---+
 *
 * Hardware enforced access rules before migration:
 *
 *  |<------- inaccessible for VF ------->|<VF owned>|<-- inaccessible for VF ->|
 *
 * GGTT nodes used for tracking allocations:
 *
 *      |<---------- balloon ------------>|<- nodes->|<----- balloon ------>|
 *
 * After the migration, GGTT area assigned to the VF might have shifted, either
 * to lower or to higher address. But we expect the total size and extra areas to
 * be identical, as migration can only happen between matching platforms.
 * Below is an example of GGTT layout of the VF after migration. Content of the
 * GGTT for VF has been moved to a new area, and we receive its address from GuC:
 *
 *  +---+----------------------+----------+---------------------------------+---+
 *  |\\\|//////////////////////|  VF mem  |/////////////////////////////////|\\\|
 *  +---+----------------------+----------+---------------------------------+---+
 *
 * Hardware enforced access rules after migration:
 *
 *  |<- inaccessible for VF -->|<VF owned>|<------- inaccessible for VF ------->|
 *
 * So the VF has a new slice of GGTT assigned, and during migration process, the
 * memory content was copied to that new area. But the &xe_ggtt nodes are still
 * tracking allocations using the old addresses. The nodes within VF owned area
 * have to be shifted, and balloon nodes need to be resized to properly mask out
 * areas not owned by the VF.
 *
 * Fixed &xe_ggtt nodes used for tracking allocations:
 *
 *     |<------ balloon ------>|<- nodes->|<----------- balloon ----------->|
 *
 * Due to use of GPU profiles, we do not expect the old and new GGTT ares to
 * overlap; but our node shifting will fix addresses properly regardless.
 */

/**
 * xe_gt_sriov_vf_fixup_ggtt_nodes - Shift GGTT allocations to match assigned range.
 * @gt: the &xe_gt struct instance
 * @shift: the shift value
 *
 * Since Global GTT is not virtualized, each VF has an assigned range
 * within the global space. This range might have changed during migration,
 * which requires all memory addresses pointing to GGTT to be shifted.
 */
void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift)
{
	struct xe_tile *tile = gt_to_tile(gt);
	struct xe_ggtt *ggtt = tile->mem.ggtt;

	xe_gt_assert(gt, !xe_gt_is_media_type(gt));

	mutex_lock(&ggtt->lock);
	xe_gt_sriov_vf_deballoon_ggtt_locked(gt);
	xe_ggtt_shift_nodes_locked(ggtt, shift);
	xe_gt_sriov_vf_balloon_ggtt_locked(gt);
	mutex_unlock(&ggtt->lock);
}

/**
 * xe_gt_sriov_vf_migrated_event_handler - Start a VF migration recovery,
 *   or just mark that a GuC is ready for it.
+0 −4
Original line number Diff line number Diff line
@@ -17,10 +17,6 @@ int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt);
int xe_gt_sriov_vf_query_config(struct xe_gt *gt);
int xe_gt_sriov_vf_connect(struct xe_gt *gt);
int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt);
int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt);
int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt);
void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt);
void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift);
int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt);
void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt);

+2 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include "xe_sriov.h"
#include "xe_sriov_printk.h"
#include "xe_sriov_vf.h"
#include "xe_tile_sriov_vf.h"

/**
 * DOC: VF restore procedure in PF KMD and VF KMD
@@ -211,7 +212,7 @@ static bool vf_post_migration_fixup_ggtt_nodes(struct xe_device *xe)
		shift = xe_gt_sriov_vf_ggtt_shift(gt);
		if (shift) {
			need_fixups = true;
			xe_gt_sriov_vf_fixup_ggtt_nodes(gt, shift);
			xe_tile_sriov_vf_fixup_ggtt_nodes(tile, shift);
		}
	}
	return need_fixups;
Loading