Skip to content

Commit 8c0aff7

Browse files
ksatya-devmwajdecz
authored andcommitted
drm/xe/pf: Create a link between PF and VF devices
When both PF and VF devices are enabled on the host, they resume simultaneously during system resume. However, the PF must finish provisioning the VF before any VFs can successfully resume. Establish a parent-child device link between the PF and VF devices to ensure the correct order of resumption. V4 -> V5: - Added missing break in the error condition. V3 -> V4: - Made xe_pci_pf_get_vf_dev() as a static function and updated input parameter types. - Updated xe_sriov_warn() to xe_sriov_abort() when VF device cannot be found. V2 -> V3: - Added function documentation for xe_pci_pf_get_vf_dev(). - Added assertion if not called from PF. V1 -> V2: - Added a helper function to get VF pci_dev. - Updated xe_sriov_notice() to xe_sriov_warn() if vf pci_dev is not found. Signed-off-by: Satyanarayana K V P <[email protected]> Cc: Michał Wajdeczko <[email protected]> Cc: Michał Winiarski <[email protected]> Cc: Piotr Piórkowski <[email protected]> Reviewed-by: Piotr Piorkowski <[email protected]> Signed-off-by: Michal Wajdeczko <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 2399bcc commit 8c0aff7

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

drivers/gpu/drm/xe/xe_pci_sriov.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,55 @@ static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs)
6262
xe_gt_sriov_pf_control_trigger_flr(gt, n);
6363
}
6464

65+
static struct pci_dev *xe_pci_pf_get_vf_dev(struct xe_device *xe, unsigned int vf_id)
66+
{
67+
struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
68+
69+
xe_assert(xe, IS_SRIOV_PF(xe));
70+
71+
/* caller must use pci_dev_put() */
72+
return pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
73+
pdev->bus->number,
74+
pci_iov_virtfn_devfn(pdev, vf_id));
75+
}
76+
77+
static void pf_link_vfs(struct xe_device *xe, int num_vfs)
78+
{
79+
struct pci_dev *pdev_pf = to_pci_dev(xe->drm.dev);
80+
struct device_link *link;
81+
struct pci_dev *pdev_vf;
82+
unsigned int n;
83+
84+
/*
85+
* When both PF and VF devices are enabled on the host, during system
86+
* resume they are resuming in parallel.
87+
*
88+
* But PF has to complete the provision of VF first to allow any VFs to
89+
* successfully resume.
90+
*
91+
* Create a parent-child device link between PF and VF devices that will
92+
* enforce correct resume order.
93+
*/
94+
for (n = 1; n <= num_vfs; n++) {
95+
pdev_vf = xe_pci_pf_get_vf_dev(xe, n - 1);
96+
97+
/* unlikely, something weird is happening, abort */
98+
if (!pdev_vf) {
99+
xe_sriov_err(xe, "Cannot find VF%u device, aborting link%s creation!\n",
100+
n, str_plural(num_vfs));
101+
break;
102+
}
103+
104+
link = device_link_add(&pdev_vf->dev, &pdev_pf->dev,
105+
DL_FLAG_AUTOREMOVE_CONSUMER);
106+
/* unlikely and harmless, continue with other VFs */
107+
if (!link)
108+
xe_sriov_notice(xe, "Failed linking VF%u\n", n);
109+
110+
pci_dev_put(pdev_vf);
111+
}
112+
}
113+
65114
static int pf_enable_vfs(struct xe_device *xe, int num_vfs)
66115
{
67116
struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
@@ -92,6 +141,8 @@ static int pf_enable_vfs(struct xe_device *xe, int num_vfs)
92141
if (err < 0)
93142
goto failed;
94143

144+
pf_link_vfs(xe, num_vfs);
145+
95146
xe_sriov_info(xe, "Enabled %u of %u VF%s\n",
96147
num_vfs, total_vfs, str_plural(total_vfs));
97148
return num_vfs;

0 commit comments

Comments
 (0)