/*
* qemu_conf.h: QEMU configuration management
*
- * Copyright (C) 2006-2007, 2009-2011 Red Hat, Inc.
+ * Copyright (C) 2006-2007, 2009-2012 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
pciDeviceList *activePciHostdevs;
usbDeviceList *activeUsbHostdevs;
+ /* The devices which is are not in use by the host or any guest. */
+ pciDeviceList *inactivePciHostdevs;
+
virBitmapPtr reservedVNCPorts;
virSysinfoDefPtr hostsysinfo;
if ((qemu_driver->activeUsbHostdevs = usbDeviceListNew()) == NULL)
goto error;
+ if ((qemu_driver->inactivePciHostdevs = pciDeviceListNew()) == NULL)
+ goto error;
+
if (privileged) {
if (chown(qemu_driver->libDir, qemu_driver->user, qemu_driver->group) < 0) {
virReportSystemError(errno,
qemuDriverLock(qemu_driver);
pciDeviceListFree(qemu_driver->activePciHostdevs);
+ pciDeviceListFree(qemu_driver->inactivePciHostdevs);
usbDeviceListFree(qemu_driver->activeUsbHostdevs);
virCapabilitiesFree(qemu_driver->caps);
pciDevice *pci;
unsigned domain, bus, slot, function;
int ret = -1;
+ bool in_inactive_list = false;
if (qemudNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
return -1;
return -1;
qemuDriverLock(driver);
- if (pciDettachDevice(pci, driver->activePciHostdevs) < 0)
+ in_inactive_list = pciDeviceListFind(driver->inactivePciHostdevs, pci);
+
+ if (pciDettachDevice(pci, driver->activePciHostdevs,
+ driver->inactivePciHostdevs) < 0)
goto out;
ret = 0;
out:
qemuDriverUnlock(driver);
- pciFreeDevice(pci);
+ if (in_inactive_list)
+ pciFreeDevice(pci);
return ret;
}
pciDeviceReAttachInit(pci);
qemuDriverLock(driver);
- if (pciReAttachDevice(pci, driver->activePciHostdevs) < 0)
+ if (pciReAttachDevice(pci, driver->activePciHostdevs,
+ driver->inactivePciHostdevs) < 0)
goto out;
ret = 0;
qemuDriverLock(driver);
- if (pciResetDevice(pci, driver->activePciHostdevs, NULL) < 0)
+ if (pciResetDevice(pci, driver->activePciHostdevs,
+ driver->inactivePciHostdevs) < 0)
goto out;
ret = 0;
/*
* qemu_hostdev.c: QEMU hostdev management
*
- * Copyright (C) 2006-2007, 2009-2011 Red Hat, Inc.
+ * Copyright (C) 2006-2007, 2009-2012 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDevice *dev = pciDeviceListGet(pcidevs, i);
if (pciDeviceGetManaged(dev) &&
- pciDettachDevice(dev, driver->activePciHostdevs) < 0)
+ pciDettachDevice(dev, driver->activePciHostdevs, NULL) < 0)
goto reattachdevs;
}
* can safely reset them */
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDevice *dev = pciDeviceListGet(pcidevs, i);
- if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0)
+ if (pciResetDevice(dev, driver->activePciHostdevs,
+ driver->inactivePciHostdevs) < 0)
goto reattachdevs;
}
}
}
- /* Loop 5: Now set the used_by_domain of the device in
+ /* Loop 5: Now remove the devices from inactive list. */
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ pciDeviceListDel(driver->inactivePciHostdevs, dev);
+ }
+
+ /* Loop 6: Now set the used_by_domain of the device in
* driver->activePciHostdevs as domain name.
*/
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDeviceSetUsedBy(activeDev, name);
}
- /* Loop 6: Now set the original states for hostdev def */
+ /* Loop 7: Now set the original states for hostdev def */
for (i = 0; i < nhostdevs; i++) {
pciDevice *dev;
pciDevice *pcidev;
pciFreeDevice(dev);
}
- /* Loop 7: Now steal all the devices from pcidevs */
+ /* Loop 8: Now steal all the devices from pcidevs */
while (pciDeviceListCount(pcidevs) > 0) {
pciDevice *dev = pciDeviceListGet(pcidevs, 0);
pciDeviceListSteal(pcidevs, dev);
reattachdevs:
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDevice *dev = pciDeviceListGet(pcidevs, i);
- pciReAttachDevice(dev, driver->activePciHostdevs);
+ pciReAttachDevice(dev, driver->activePciHostdevs, NULL);
}
cleanup:
{
int retries = 100;
- if (!pciDeviceGetManaged(dev))
+ /* If the device is not managed and was attached to guest
+ * successfully, it must have been inactive.
+ */
+ if (!pciDeviceGetManaged(dev)) {
+ pciDeviceListAdd(driver->inactivePciHostdevs, dev);
return;
+ }
while (pciWaitForDeviceCleanup(dev, "kvm_assigned_device")
&& retries) {
retries--;
}
- if (pciReAttachDevice(dev, driver->activePciHostdevs) < 0) {
+ if (pciReAttachDevice(dev, driver->activePciHostdevs,
+ driver->inactivePciHostdevs) < 0) {
virErrorPtr err = virGetLastError();
VIR_ERROR(_("Failed to re-attach PCI device: %s"),
err ? err->message : _("unknown error"));
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDevice *dev = pciDeviceListGet(pcidevs, i);
- if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0) {
+ if (pciResetDevice(dev, driver->activePciHostdevs,
+ driver->inactivePciHostdevs) < 0) {
virErrorPtr err = virGetLastError();
VIR_ERROR(_("Failed to reset PCI device: %s"),
err ? err->message : _("unknown error"));
detach->source.subsys.u.pci.function);
if (pci) {
activePci = pciDeviceListSteal(driver->activePciHostdevs, pci);
- if (pciResetDevice(activePci, driver->activePciHostdevs, NULL))
+ if (pciResetDevice(activePci, driver->activePciHostdevs,
+ driver->inactivePciHostdevs) == 0)
qemuReattachPciDevice(activePci, driver);
else
ret = -1;
}
int
-pciDettachDevice(pciDevice *dev, pciDeviceList *activeDevs)
+pciDettachDevice(pciDevice *dev,
+ pciDeviceList *activeDevs,
+ pciDeviceList *inactiveDevs)
{
const char *driver = pciFindStubDriver();
if (!driver) {
return -1;
}
- return pciBindDeviceToStub(dev, driver);
+ if (pciBindDeviceToStub(dev, driver) < 0)
+ return -1;
+
+ /* Add the dev into list inactiveDevs */
+ if (inactiveDevs && !pciDeviceListFind(inactiveDevs, dev)) {
+ if (pciDeviceListAdd(inactiveDevs, dev) < 0)
+ return -1;
+ }
+
+ return 0;
}
int
-pciReAttachDevice(pciDevice *dev, pciDeviceList *activeDevs)
+pciReAttachDevice(pciDevice *dev,
+ pciDeviceList *activeDevs,
+ pciDeviceList *inactiveDevs)
{
const char *driver = pciFindStubDriver();
if (!driver) {
return -1;
}
- return pciUnbindDeviceFromStub(dev, driver);
+ if (pciUnbindDeviceFromStub(dev, driver) < 0)
+ return -1;
+
+ /* Steal the dev from list inactiveDevs */
+ if (inactiveDevs)
+ pciDeviceListSteal(inactiveDevs, dev);
+
+ return 0;
}
/* Certain hypervisors (like qemu/kvm) map the PCI bar(s) on
unsigned function);
void pciFreeDevice (pciDevice *dev);
const char *pciDeviceGetName (pciDevice *dev);
-int pciDettachDevice (pciDevice *dev, pciDeviceList *activeDevs);
-int pciReAttachDevice (pciDevice *dev, pciDeviceList *activeDevs);
+int pciDettachDevice (pciDevice *dev,
+ pciDeviceList *activeDevs,
+ pciDeviceList *inactiveDevs);
+int pciReAttachDevice (pciDevice *dev,
+ pciDeviceList *activeDevs,
+ pciDeviceList *inactiveDevs);
int pciResetDevice (pciDevice *dev,
pciDeviceList *activeDevs,
pciDeviceList *inactiveDevs);
if (!pci)
return -1;
- if (pciDettachDevice(pci, NULL) < 0)
+ if (pciDettachDevice(pci, NULL, NULL) < 0)
goto out;
ret = 0;
goto out;
}
- if (pciReAttachDevice(pci, NULL) < 0)
+ if (pciReAttachDevice(pci, NULL, NULL) < 0)
goto out;
ret = 0;