Files
linux/drivers/gpu/drm/xe/xe_sriov_pf_control.c
Michał Winiarski 3b358c21f9 drm/xe/pf: Add wait helper for VF FLR
VF FLR requires additional processing done by PF driver.
The processing is done after FLR is already finished from PCIe
perspective.
In order to avoid a scenario where migration state transitions while
PF processing is still in progress, additional synchronization
point is needed.
Add a helper that will be used as part of VF driver struct
pci_error_handlers .reset_done() callback.

Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Link: https://patch.msgid.link/20251112132220.516975-24-michal.winiarski@intel.com
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
2025-11-13 11:48:20 +01:00

280 lines
5.8 KiB
C

// SPDX-License-Identifier: MIT
/*
* Copyright © 2025 Intel Corporation
*/
#include "xe_device.h"
#include "xe_gt_sriov_pf_control.h"
#include "xe_gt_sriov_pf_migration.h"
#include "xe_sriov_packet.h"
#include "xe_sriov_pf_control.h"
#include "xe_sriov_printk.h"
/**
* xe_sriov_pf_control_pause_vf() - Pause a VF on all GTs.
* @xe: the &xe_device
* @vfid: the VF identifier (can't be 0 == PFID)
*
* This function is for PF only.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_sriov_pf_control_pause_vf(struct xe_device *xe, unsigned int vfid)
{
struct xe_gt *gt;
unsigned int id;
int result = 0;
int err;
for_each_gt(gt, xe, id) {
err = xe_gt_sriov_pf_control_pause_vf(gt, vfid);
result = result ? -EUCLEAN : err;
}
if (result)
return result;
xe_sriov_info(xe, "VF%u paused!\n", vfid);
return 0;
}
/**
* xe_sriov_pf_control_resume_vf() - Resume a VF on all GTs.
* @xe: the &xe_device
* @vfid: the VF identifier
*
* This function is for PF only.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_sriov_pf_control_resume_vf(struct xe_device *xe, unsigned int vfid)
{
struct xe_gt *gt;
unsigned int id;
int result = 0;
int err;
for_each_gt(gt, xe, id) {
err = xe_gt_sriov_pf_control_resume_vf(gt, vfid);
result = result ? -EUCLEAN : err;
}
if (result)
return result;
xe_sriov_info(xe, "VF%u resumed!\n", vfid);
return 0;
}
/**
* xe_sriov_pf_control_stop_vf - Stop a VF on all GTs.
* @xe: the &xe_device
* @vfid: the VF identifier
*
* This function is for PF only.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_sriov_pf_control_stop_vf(struct xe_device *xe, unsigned int vfid)
{
struct xe_gt *gt;
unsigned int id;
int result = 0;
int err;
for_each_gt(gt, xe, id) {
err = xe_gt_sriov_pf_control_stop_vf(gt, vfid);
result = result ? -EUCLEAN : err;
}
if (result)
return result;
xe_sriov_info(xe, "VF%u stopped!\n", vfid);
return 0;
}
/**
* xe_sriov_pf_control_reset_vf() - Perform a VF reset (FLR).
* @xe: the &xe_device
* @vfid: the VF identifier
*
* This function is for PF only.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_sriov_pf_control_reset_vf(struct xe_device *xe, unsigned int vfid)
{
struct xe_gt *gt;
unsigned int id;
int result = 0;
int err;
for_each_gt(gt, xe, id) {
err = xe_gt_sriov_pf_control_trigger_flr(gt, vfid);
result = result ? -EUCLEAN : err;
}
for_each_gt(gt, xe, id) {
err = xe_gt_sriov_pf_control_wait_flr(gt, vfid);
result = result ? -EUCLEAN : err;
}
return result;
}
/**
* xe_sriov_pf_control_wait_flr() - Wait for a VF reset (FLR) to complete.
* @xe: the &xe_device
* @vfid: the VF identifier
*
* This function is for PF only.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_sriov_pf_control_wait_flr(struct xe_device *xe, unsigned int vfid)
{
struct xe_gt *gt;
unsigned int id;
int result = 0;
int err;
for_each_gt(gt, xe, id) {
err = xe_gt_sriov_pf_control_wait_flr(gt, vfid);
result = result ? -EUCLEAN : err;
}
return result;
}
/**
* xe_sriov_pf_control_sync_flr() - Synchronize a VF FLR between all GTs.
* @xe: the &xe_device
* @vfid: the VF identifier
*
* This function is for PF only.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_sriov_pf_control_sync_flr(struct xe_device *xe, unsigned int vfid)
{
struct xe_gt *gt;
unsigned int id;
int ret;
for_each_gt(gt, xe, id) {
ret = xe_gt_sriov_pf_control_sync_flr(gt, vfid, false);
if (ret < 0)
return ret;
}
for_each_gt(gt, xe, id) {
ret = xe_gt_sriov_pf_control_sync_flr(gt, vfid, true);
if (ret < 0)
return ret;
}
return 0;
}
/**
* xe_sriov_pf_control_trigger_save_vf() - Start VF migration data SAVE sequence on all GTs.
* @xe: the &xe_device
* @vfid: the VF identifier
*
* This function is for PF only.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_sriov_pf_control_trigger_save_vf(struct xe_device *xe, unsigned int vfid)
{
struct xe_gt *gt;
unsigned int id;
int ret;
ret = xe_sriov_packet_save_init(xe, vfid);
if (ret)
return ret;
for_each_gt(gt, xe, id) {
xe_gt_sriov_pf_migration_save_init(gt, vfid);
ret = xe_gt_sriov_pf_control_trigger_save_vf(gt, vfid);
if (ret)
return ret;
}
return 0;
}
/**
* xe_sriov_pf_control_finish_save_vf() - Complete VF migration data SAVE sequence on all GTs.
* @xe: the &xe_device
* @vfid: the VF identifier
*
* This function is for PF only.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_sriov_pf_control_finish_save_vf(struct xe_device *xe, unsigned int vfid)
{
struct xe_gt *gt;
unsigned int id;
int ret;
for_each_gt(gt, xe, id) {
ret = xe_gt_sriov_pf_control_finish_save_vf(gt, vfid);
if (ret)
break;
}
return ret;
}
/**
* xe_sriov_pf_control_trigger_restore_vf() - Start VF migration data RESTORE sequence on all GTs.
* @xe: the &xe_device
* @vfid: the VF identifier
*
* This function is for PF only.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_sriov_pf_control_trigger_restore_vf(struct xe_device *xe, unsigned int vfid)
{
struct xe_gt *gt;
unsigned int id;
int ret;
for_each_gt(gt, xe, id) {
ret = xe_gt_sriov_pf_control_trigger_restore_vf(gt, vfid);
if (ret)
return ret;
}
return ret;
}
/**
* xe_sriov_pf_control_finish_restore_vf() - Complete VF migration data RESTORE sequence on all GTs.
* @xe: the &xe_device
* @vfid: the VF identifier
*
* This function is for PF only.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_sriov_pf_control_finish_restore_vf(struct xe_device *xe, unsigned int vfid)
{
struct xe_gt *gt;
unsigned int id;
int ret;
for_each_gt(gt, xe, id) {
ret = xe_gt_sriov_pf_control_finish_restore_vf(gt, vfid);
if (ret)
break;
}
return ret;
}