Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx> --- src/libvirt_private.syms | 2 ++ src/util/virpci.c | 71 ++++++++++++++++++++++++++++-------------------- src/util/virpci.h | 5 ++++ 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 91d1304..68140e6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1581,6 +1581,7 @@ virPCIDeviceCopy; virPCIDeviceDetach; virPCIDeviceFileIterate; virPCIDeviceFree; +virPCIDeviceGetDriverPathAndName; virPCIDeviceGetIOMMUGroupDev; virPCIDeviceGetIOMMUGroupList; virPCIDeviceGetManaged; @@ -1612,6 +1613,7 @@ virPCIDeviceSetReprobe; virPCIDeviceSetStubDriver; virPCIDeviceSetUnbindFromStub; virPCIDeviceSetUsedBy; +virPCIDeviceUnbind; virPCIDeviceWaitForCleanup; virPCIGetNetName; virPCIGetPhysicalFunction; diff --git a/src/util/virpci.c b/src/util/virpci.c index f6ab794..e2d222e 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -225,7 +225,7 @@ virPCIFile(char **buffer, const char *device, const char *file) * * Return 0 for success, -1 for error. */ -static int +int virPCIDeviceGetDriverPathAndName(virPCIDevicePtr dev, char **path, char **name) { int ret = -1; @@ -1005,6 +1005,44 @@ recheck: return -1; } +int +virPCIDeviceUnbind(virPCIDevicePtr dev, bool reprobe) +{ + char *path = NULL; + char *drvpath = NULL; + char *driver = NULL; + int ret = -1; + + if (virPCIDeviceGetDriverPathAndName(dev, &drvpath, &driver) < 0) + goto cleanup; + + if (!driver) { + /* The device is not bound to any driver */ + ret = 0; + goto cleanup; + } + + if (virPCIFile(&path, dev->name, "driver/unbind") < 0) + goto cleanup; + + if (virFileExists(path)) { + if (virFileWriteStr(path, dev->name, 0) < 0) { + virReportSystemError(errno, + _("Failed to unbind PCI device '%s' from %s"), + dev->name, driver); + goto cleanup; + } + dev->reprobe = reprobe; + } + + ret = 0; +cleanup: + VIR_FREE(path); + VIR_FREE(drvpath); + VIR_FREE(driver); + return ret; +} + static const char *virPCIKnownStubs[] = { "pciback", /* used by xen */ "pci-stub", /* used by kvm legacy passthrough */ @@ -1047,18 +1085,8 @@ virPCIDeviceUnbindFromStub(virPCIDevicePtr dev) if (!isStub) goto remove_slot; - if (virFileExists(drvdir)) { - if (virPCIDriverFile(&path, driver, "unbind") < 0) { - goto cleanup; - } - - if (virFileWriteStr(path, dev->name, 0) < 0) { - virReportSystemError(errno, - _("Failed to unbind PCI device '%s' from %s"), - dev->name, driver); - goto cleanup; - } - } + if (virPCIDeviceUnbind(dev, dev->reprobe) < 0) + goto cleanup; dev->unbind_from_stub = false; remove_slot: @@ -1174,24 +1202,9 @@ virPCIDeviceBindToStub(virPCIDevicePtr dev, goto remove_id; } - /* If the device is already bound to a driver, unbind it. - * Note, this will have rather unpleasant side effects if this - * PCI device happens to be IDE controller for the disk hosting - * your root filesystem. - */ - if (virPCIFile(&path, dev->name, "driver/unbind") < 0) + if (virPCIDeviceUnbind(dev, reprobe) < 0) goto remove_id; - if (virFileExists(path)) { - if (virFileWriteStr(path, dev->name, 0) < 0) { - virReportSystemError(errno, - _("Failed to unbind PCI device '%s'"), - dev->name); - goto remove_id; - } - dev->reprobe = reprobe; - } - /* If the device isn't already bound to pci-stub, try binding it now. */ if (!virFileLinkPointsTo(driverLink, stubDriverPath)) { diff --git a/src/util/virpci.h b/src/util/virpci.h index 08bf4c3..42c3c95 100644 --- a/src/util/virpci.h +++ b/src/util/virpci.h @@ -167,4 +167,9 @@ int virPCIDeviceAddressParse(char *address, virPCIDeviceAddressPtr bdf); int virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path, char **pfname, int *vf_index); +int virPCIDeviceUnbind(virPCIDevicePtr dev, bool reprobe); +int virPCIDeviceGetDriverPathAndName(virPCIDevicePtr dev, + char **path, + char **name); + #endif /* __VIR_PCI_H__ */ -- 1.8.5.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list