Commit 6e6d7b41 authored by Tomasz Lis's avatar Tomasz Lis Committed by Michal Wajdeczko
Browse files

drm/xe/vf: React to MIGRATED interrupt



To properly support VF Save/Restore procedure, fixups need to be
applied after PF driver finishes its part of VF Restore. The fixups
are required to adjust the ongoing execution for a hardware switch
that happened, because some GFX resources are not fully virtualized,
and assigned to a VF as range from a global pool. The VF on which
a VM is restored will often have different ranges provisioned than
the VF on which save process happened. Those resource fixups are
applied by the VF driver within a restored VM.

A VF driver gets informed that it was migrated by receiving an
interrupt from each GuC. The interrupt assigned for that purpose
is "GUC SW interrupt 0". Seeing that fields set from within the
irq handler should be the trigger for fixups.

The VF can safely do post-migration fixups on resources associated
to each GuC only after that GuC issued the MIGRATED interrupt.

This change introduces a worker to be used for post-migration fixups,
and a mechanism to schedule said worker when all GuCs sent the irq.

v2: renamed and moved functions, updated logged messages, removed
  unused includes, used anon struct (Michal)
v3: ordering, kerneldoc, asserts, debug messages,
  on_all_tiles -> on_all_gts (Michal)
v4: fixed missing header include
v5: Explained what fixups are, explained which IRQ is used, style
  fixes (Michal)

Bspec: 50868
Signed-off-by: default avatarTomasz Lis <tomasz.lis@intel.com>
Reviewed-by: default avatarMichal Wajdeczko <michal.wajdeczko@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241104213449.1455694-2-tomasz.lis@intel.com


Signed-off-by: default avatarMichal Wajdeczko <michal.wajdeczko@intel.com>
parent 20ade9c3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -125,7 +125,8 @@ xe-y += \
	xe_gt_sriov_vf.o \
	xe_guc_relay.o \
	xe_memirq.o \
	xe_sriov.o
	xe_sriov.o \
	xe_sriov_vf.o

xe-$(CONFIG_PCI_IOV) += \
	xe_gt_sriov_pf.o \
+2 −0
Original line number Diff line number Diff line
@@ -374,6 +374,8 @@ struct xe_device {

		/** @sriov.pf: PF specific data */
		struct xe_device_pf pf;
		/** @sriov.vf: VF specific data */
		struct xe_device_vf vf;

		/** @sriov.wq: workqueue used by the virtualization workers */
		struct workqueue_struct *wq;
+25 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "xe_guc_relay.h"
#include "xe_mmio.h"
#include "xe_sriov.h"
#include "xe_sriov_vf.h"
#include "xe_uc_fw.h"
#include "xe_wopcm.h"

@@ -692,6 +693,30 @@ int xe_gt_sriov_vf_connect(struct xe_gt *gt)
	return err;
}

/**
 * xe_gt_sriov_vf_migrated_event_handler - Start a VF migration recovery,
 *   or just mark that a GuC is ready for it.
 * @gt: the &xe_gt struct instance linked to target GuC
 *
 * This function shall be called only by VF.
 */
void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt)
{
	struct xe_device *xe = gt_to_xe(gt);

	xe_gt_assert(gt, IS_SRIOV_VF(xe));

	set_bit(gt->info.id, &xe->sriov.vf.migration.gt_flags);
	/*
	 * We need to be certain that if all flags were set, at least one
	 * thread will notice that and schedule the recovery.
	 */
	smp_mb__after_atomic();

	xe_gt_sriov_info(gt, "ready for recovery after migration\n");
	xe_sriov_vf_start_migration_recovery(xe);
}

static bool vf_is_negotiated(struct xe_gt *gt, u16 major, u16 minor)
{
	xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt)));
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ 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);
void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt);

u32 xe_gt_sriov_vf_gmdid(struct xe_gt *gt);
u16 xe_gt_sriov_vf_guc_ids(struct xe_gt *gt);
+11 −0
Original line number Diff line number Diff line
@@ -1099,10 +1099,21 @@ int xe_guc_self_cfg64(struct xe_guc *guc, u16 key, u64 val)
	return guc_self_cfg(guc, key, 2, val);
}

static void xe_guc_sw_0_irq_handler(struct xe_guc *guc)
{
	struct xe_gt *gt = guc_to_gt(guc);

	if (IS_SRIOV_VF(gt_to_xe(gt)))
		xe_gt_sriov_vf_migrated_event_handler(gt);
}

void xe_guc_irq_handler(struct xe_guc *guc, const u16 iir)
{
	if (iir & GUC_INTR_GUC2HOST)
		xe_guc_ct_irq_handler(&guc->ct);

	if (iir & GUC_INTR_SW_INT_0)
		xe_guc_sw_0_irq_handler(guc);
}

void xe_guc_sanitize(struct xe_guc *guc)
Loading