virpci: Drop newid style of PCI device detach

As stated in 84f9358b18 all kernels that we are interested in
have 'drivers_override'. Drop the other, older style of
overriding PCI device driver - newid.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Tested-by: Daniel Henrique Barboza <danielhb413@gmail.com>
This commit is contained in:
Michal Privoznik 2019-08-20 13:17:44 +02:00
parent d5b07eae6e
commit fd69a0189c

View File

@ -218,16 +218,6 @@ virPCIDriverDir(const char *driver)
}
static char *
virPCIDriverFile(const char *driver, const char *file)
{
char *buffer;
ignore_value(virAsprintf(&buffer, PCI_SYSFS "drivers/%s/%s", driver, file));
return buffer;
}
static char *
virPCIFile(const char *device, const char *file)
{
@ -1145,104 +1135,6 @@ virPCIDeviceBindWithDriverOverride(virPCIDevicePtr dev,
return 0;
}
static int
virPCIDeviceUnbindFromStubWithNewid(virPCIDevicePtr dev)
{
int result = -1;
VIR_AUTOFREE(char *) drvdir = NULL;
VIR_AUTOFREE(char *) path = NULL;
VIR_AUTOFREE(char *) driver = NULL;
/* If the device is currently bound to one of the "well known"
* stub drivers, then unbind it, otherwise ignore it.
*/
if (virPCIDeviceGetDriverPathAndName(dev, &drvdir, &driver) < 0)
goto cleanup;
if (!driver) {
/* The device is not bound to any driver and we are almost done. */
VIR_DEBUG("PCI device %s is not bound to any driver", dev->name);
goto reprobe;
}
if (!dev->unbind_from_stub) {
VIR_DEBUG("Unbind from stub skipped for PCI device %s", dev->name);
goto remove_slot;
}
/* If the device isn't bound to a known stub, skip the unbind. */
if (virPCIStubDriverTypeFromString(driver) < 0 ||
virPCIStubDriverTypeFromString(driver) == VIR_PCI_STUB_DRIVER_NONE) {
VIR_DEBUG("Unbind from stub skipped for PCI device %s because of "
"unknown stub driver", dev->name);
goto remove_slot;
}
VIR_DEBUG("Unbinding PCI device %s from stub driver %s",
dev->name, driver);
if (virPCIDeviceUnbind(dev) < 0)
goto cleanup;
dev->unbind_from_stub = false;
remove_slot:
if (!dev->remove_slot) {
VIR_DEBUG("Slot removal skipped for PCI device %s", dev->name);
goto reprobe;
}
VIR_DEBUG("Removing slot for PCI device %s", dev->name);
/* Xen's pciback.ko wants you to use remove_slot on the specific device */
if (!(path = virPCIDriverFile(driver, "remove_slot")))
goto cleanup;
if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) {
virReportSystemError(errno,
_("Failed to remove slot for PCI device '%s' from %s"),
dev->name, driver);
goto cleanup;
}
dev->remove_slot = false;
reprobe:
if (!dev->reprobe) {
VIR_DEBUG("Reprobe skipped for PCI device %s", dev->name);
result = 0;
goto cleanup;
}
VIR_DEBUG("Reprobing for PCI device %s", dev->name);
/* Trigger a re-probe of the device is not in the stub's dynamic
* ID table. If the stub is available, but 'remove_id' isn't
* available, then re-probing would just cause the device to be
* re-bound to the stub.
*/
VIR_FREE(path);
if (driver && !(path = virPCIDriverFile(driver, "remove_id")))
goto cleanup;
if (!driver || !virFileExists(drvdir) || virFileExists(path)) {
if (virFileWriteStr(PCI_SYSFS "drivers_probe", dev->name, 0) < 0) {
virReportSystemError(errno,
_("Failed to trigger a re-probe for PCI device '%s'"),
dev->name);
goto cleanup;
}
}
result = 0;
cleanup:
/* do not do it again */
dev->unbind_from_stub = false;
dev->remove_slot = false;
dev->reprobe = false;
return result;
}
static int
virPCIDeviceUnbindFromStubWithOverride(virPCIDevicePtr dev)
{
@ -1257,167 +1149,7 @@ virPCIDeviceUnbindFromStubWithOverride(virPCIDevicePtr dev)
static int
virPCIDeviceUnbindFromStub(virPCIDevicePtr dev)
{
VIR_AUTOFREE(char *) path = NULL;
/*
* Prefer using the device's driver_override interface, falling back
* to the unpleasant new_id interface.
*/
if (!(path = virPCIFile(dev->name, "driver_override")))
return -1;
if (virFileExists(path))
return virPCIDeviceUnbindFromStubWithOverride(dev);
return virPCIDeviceUnbindFromStubWithNewid(dev);
}
static int
virPCIDeviceBindToStubWithNewid(virPCIDevicePtr dev)
{
int result = -1;
bool reprobe = false;
VIR_AUTOFREE(char *) stubDriverPath = NULL;
VIR_AUTOFREE(char *) driverLink = NULL;
VIR_AUTOFREE(char *) path = NULL; /* reused for different purposes */
VIR_AUTOPTR(virError) err = NULL;
const char *stubDriverName = NULL;
/* Check the device is configured to use one of the known stub drivers */
if (dev->stubDriver == VIR_PCI_STUB_DRIVER_NONE) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("No stub driver configured for PCI device %s"),
dev->name);
return -1;
} else if (!(stubDriverName = virPCIStubDriverTypeToString(dev->stubDriver))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unknown stub driver configured for PCI device %s"),
dev->name);
return -1;
}
if (!(stubDriverPath = virPCIDriverDir(stubDriverName)) ||
!(driverLink = virPCIFile(dev->name, "driver")))
goto cleanup;
if (virFileExists(driverLink)) {
if (virFileLinkPointsTo(driverLink, stubDriverPath)) {
/* The device is already bound to the correct driver */
VIR_DEBUG("Device %s is already bound to %s",
dev->name, stubDriverName);
result = 0;
goto cleanup;
}
reprobe = true;
}
/* Add the PCI device ID to the stub's dynamic ID table;
* this is needed to allow us to bind the device to the stub.
* Note: if the device is not currently bound to any driver,
* stub will immediately be bound to the device. Also, note
* that if a new device with this ID is hotplugged, or if a probe
* is triggered for such a device, it will also be immediately
* bound by the stub.
*/
if (!(path = virPCIDriverFile(stubDriverName, "new_id")))
goto cleanup;
if (virFileWriteStr(path, dev->id, 0) < 0) {
virReportSystemError(errno,
_("Failed to add PCI device ID '%s' to %s"),
dev->id, stubDriverName);
goto cleanup;
}
/* check whether the device is bound to pci-stub when we write dev->id to
* ${stubDriver}/new_id.
*/
if (virFileLinkPointsTo(driverLink, stubDriverPath)) {
dev->unbind_from_stub = true;
dev->remove_slot = true;
result = 0;
goto remove_id;
}
if (virPCIDeviceUnbind(dev) < 0)
goto remove_id;
/* If the device was bound to a driver we'll need to reprobe later */
dev->reprobe = reprobe;
/* If the device isn't already bound to pci-stub, try binding it now.
*/
if (!virFileLinkPointsTo(driverLink, stubDriverPath)) {
/* Xen's pciback.ko wants you to use new_slot first */
VIR_FREE(path);
if (!(path = virPCIDriverFile(stubDriverName, "new_slot")))
goto remove_id;
if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) {
virReportSystemError(errno,
_("Failed to add slot for "
"PCI device '%s' to %s"),
dev->name, stubDriverName);
goto remove_id;
}
dev->remove_slot = true;
VIR_FREE(path);
if (!(path = virPCIDriverFile(stubDriverName, "bind")))
goto remove_id;
if (virFileWriteStr(path, dev->name, 0) < 0) {
virReportSystemError(errno,
_("Failed to bind PCI device '%s' to %s"),
dev->name, stubDriverName);
goto remove_id;
}
dev->unbind_from_stub = true;
}
result = 0;
remove_id:
err = virSaveLastError();
/* If 'remove_id' exists, remove the device id from pci-stub's dynamic
* ID table so that 'drivers_probe' works below.
*/
VIR_FREE(path);
if (!(path = virPCIDriverFile(stubDriverName, "remove_id"))) {
/* We do not remove PCI ID from pci-stub, and we cannot reprobe it */
if (dev->reprobe) {
VIR_WARN("Could not remove PCI ID '%s' from %s, and the device "
"cannot be probed again.", dev->id, stubDriverName);
}
dev->reprobe = false;
result = -1;
goto cleanup;
}
if (virFileExists(path) && virFileWriteStr(path, dev->id, 0) < 0) {
virReportSystemError(errno,
_("Failed to remove PCI ID '%s' from %s"),
dev->id, stubDriverName);
/* remove PCI ID from pci-stub failed, and we cannot reprobe it */
if (dev->reprobe) {
VIR_WARN("Failed to remove PCI ID '%s' from %s, and the device "
"cannot be probed again.", dev->id, stubDriverName);
}
dev->reprobe = false;
result = -1;
goto cleanup;
}
cleanup:
if (result < 0)
virPCIDeviceUnbindFromStub(dev);
if (err)
virSetError(err);
return result;
return virPCIDeviceUnbindFromStubWithOverride(dev);
}
static int
@ -1463,19 +1195,7 @@ virPCIDeviceBindToStubWithOverride(virPCIDevicePtr dev)
static int
virPCIDeviceBindToStub(virPCIDevicePtr dev)
{
VIR_AUTOFREE(char *) path = NULL;
/*
* Prefer using the device's driver_override interface, falling back
* to the unpleasant new_id interface.
*/
if (!(path = virPCIFile(dev->name, "driver_override")))
return -1;
if (virFileExists(path))
return virPCIDeviceBindToStubWithOverride(dev);
return virPCIDeviceBindToStubWithNewid(dev);
return virPCIDeviceBindToStubWithOverride(dev);
}
/* virPCIDeviceDetach: