The vfio-pci hot-reset interface VFIO_DEVICE_PCI_HOT_RESET does not take into account whether an SR-IOV PF has active VFs. The VFs appear on a virtual bus, which is not enumerated in collecting affected devices. Move the burden to the user when active VFs are present, require that there are no VFs present on SR-IOV capable PFs in order to conduct a hot reset. Fixes: 137e5531351d ("vfio/pci: Add sriov_configure support") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Alex Williamson --- drivers/vfio/pci/vfio_pci_core.c | 15 +++++++++++++-- include/uapi/linux/vfio.h | 3 +++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index 9757b171791c..956a05ca12e5 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -894,6 +894,17 @@ static int vfio_pci_count_devs(struct pci_dev *pdev, void *data) return 0; } +/* + * PCI walk callback to check for SR-IOV PFs with active VFs. VFs are not + * enumerated when determining affected devices and may be owned by separate + * userspace processes from the PF. It's therefore the user's responsibility + * to teardown VFs for any affected PF before performing a hot-reset. + */ +static int vfio_pci_dev_has_vfs(struct pci_dev *pdev, void *data) +{ + return pci_num_vf(pdev) ? -EBUSY : 0; +} + struct vfio_pci_fill_info { struct vfio_device *vdev; struct vfio_pci_dependent_device *devices; @@ -2598,7 +2609,7 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set, list_for_each_entry(vdev, &dev_set->device_list, vdev.dev_set_list) vfio_pci_set_power_state(vdev, PCI_D0); - ret = pci_reset_bus(pdev); + ret = pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL); vdev = list_last_entry(&dev_set->device_list, struct vfio_pci_core_device, vdev.dev_set_list); @@ -2661,7 +2672,7 @@ static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set) if (vfio_pci_dev_set_pm_runtime_get(dev_set)) return; - if (!pci_reset_bus(pdev)) + if (!pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL)) reset_done = true; list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) { diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index 5de618a3a5ee..8603959f1735 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h @@ -772,6 +772,9 @@ struct vfio_pci_hot_reset_info { * Mixed usage of legacy groups and cdevs across the set of affected * devices is not supported. * + * Hot reset of SR-IOV PFs with active VFs is not supported, SR-IOV + * should first be disabled on any affected PF. + * * Return: 0 on success, -errno on failure. */ struct vfio_pci_hot_reset { -- 2.53.0