mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-14 16:45:20 +00:00
virpci: Drop newid style of PCI device detach
As stated in 84f9358b18346 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:
parent
d5b07eae6e
commit
fd69a0189c
@ -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 *
|
static char *
|
||||||
virPCIFile(const char *device, const char *file)
|
virPCIFile(const char *device, const char *file)
|
||||||
{
|
{
|
||||||
@ -1145,104 +1135,6 @@ virPCIDeviceBindWithDriverOverride(virPCIDevicePtr dev,
|
|||||||
return 0;
|
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
|
static int
|
||||||
virPCIDeviceUnbindFromStubWithOverride(virPCIDevicePtr dev)
|
virPCIDeviceUnbindFromStubWithOverride(virPCIDevicePtr dev)
|
||||||
{
|
{
|
||||||
@ -1257,167 +1149,7 @@ virPCIDeviceUnbindFromStubWithOverride(virPCIDevicePtr dev)
|
|||||||
static int
|
static int
|
||||||
virPCIDeviceUnbindFromStub(virPCIDevicePtr dev)
|
virPCIDeviceUnbindFromStub(virPCIDevicePtr dev)
|
||||||
{
|
{
|
||||||
VIR_AUTOFREE(char *) path = NULL;
|
return virPCIDeviceUnbindFromStubWithOverride(dev);
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1463,19 +1195,7 @@ virPCIDeviceBindToStubWithOverride(virPCIDevicePtr dev)
|
|||||||
static int
|
static int
|
||||||
virPCIDeviceBindToStub(virPCIDevicePtr dev)
|
virPCIDeviceBindToStub(virPCIDevicePtr dev)
|
||||||
{
|
{
|
||||||
VIR_AUTOFREE(char *) path = NULL;
|
return virPCIDeviceBindToStubWithOverride(dev);
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virPCIDeviceDetach:
|
/* virPCIDeviceDetach:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user