virDomainDefPtr def)
{
pciDeviceList *pcidevs;
- int i, ret;
+ int ret = -1;
if (!def->nhostdevs)
return 0;
if (!(pcidevs = qemuGetPciHostDeviceList(NULL, def)))
return -1;
- ret = 0;
-
- for (i = 0; i < pcidevs->count; i++) {
+ while (pciDeviceListCount(pcidevs) > 0) {
+ pciDevice *dev = pciDeviceListSteal(NULL, pcidevs, 0);
if (pciDeviceListAdd(NULL,
driver->activePciHostdevs,
- pcidevs->devs[i]) < 0) {
- ret = -1;
- break;
+ dev) < 0) {
+ pciFreeDevice(NULL, dev);
+ goto cleanup;
}
- pcidevs->devs[i] = NULL;
}
+ ret = 0;
+
+cleanup:
pciDeviceListFree(NULL, pcidevs);
return ret;
}
{
pciDeviceList *pcidevs;
int i;
+ int ret = -1;
if (!def->nhostdevs)
return 0;
* to pci-stub.ko
*/
- for (i = 0; i < pcidevs->count; i++)
- if (pciDeviceGetManaged(pcidevs->devs[i]) &&
- pciDettachDevice(conn, pcidevs->devs[i]) < 0)
- goto error;
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ if (pciDeviceGetManaged(dev) &&
+ pciDettachDevice(conn, dev) < 0)
+ goto cleanup;
+ }
/* Now that all the PCI hostdevs have be dettached, we can safely
* reset them */
- for (i = 0; i < pcidevs->count; i++)
- if (pciResetDevice(conn, pcidevs->devs[i],
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ if (pciResetDevice(conn, dev,
driver->activePciHostdevs) < 0)
- goto error;
+ goto cleanup;
+ }
/* Now mark all the devices as active */
- for (i = 0; i < pcidevs->count; i++) {
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ pciDeviceListSteal(NULL, pcidevs, dev);
if (pciDeviceListAdd(conn,
driver->activePciHostdevs,
- pcidevs->devs[i]) < 0)
- goto error;
- pcidevs->devs[i] = NULL;
+ dev) < 0) {
+ pciFreeDevice(NULL, dev);
+ goto cleanup;
+ }
}
- pciDeviceListFree(conn, pcidevs);
- return 0;
+ ret = 0;
-error:
+cleanup:
pciDeviceListFree(conn, pcidevs);
- return -1;
+ return ret;
}
static void
/* Again 3 loops; mark all devices as inactive before reset
* them and reset all the devices before re-attach */
- for (i = 0; i < pcidevs->count; i++)
- pciDeviceListDel(conn, driver->activePciHostdevs, pcidevs->devs[i]);
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ pciDeviceListDel(conn, driver->activePciHostdevs, dev);
+ }
- for (i = 0; i < pcidevs->count; i++)
- if (pciResetDevice(conn, pcidevs->devs[i],
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ if (pciResetDevice(conn, dev,
driver->activePciHostdevs) < 0) {
virErrorPtr err = virGetLastError();
VIR_ERROR(_("Failed to reset PCI device: %s\n"),
err ? err->message : "");
virResetError(err);
}
+ }
- for (i = 0; i < pcidevs->count; i++)
- if (pciDeviceGetManaged(pcidevs->devs[i]) &&
- pciReAttachDevice(conn, pcidevs->devs[i]) < 0) {
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ if (pciDeviceGetManaged(dev) &&
+ pciReAttachDevice(NULL, dev) < 0) {
virErrorPtr err = virGetLastError();
VIR_ERROR(_("Failed to re-attach PCI device: %s\n"),
err ? err->message : "");
virResetError(err);
}
+ }
pciDeviceListFree(conn, pcidevs);
}
unsigned managed : 1;
};
+struct _pciDeviceList {
+ unsigned count;
+ pciDevice **devs;
+};
+
+
/* For virReportOOMError() and virReportSystemError() */
#define VIR_FROM_THIS VIR_FROM_NONE
return 0;
}
-void
-pciDeviceListDel(virConnectPtr conn ATTRIBUTE_UNUSED,
- pciDeviceList *list,
- pciDevice *dev)
+pciDevice *
+pciDeviceListGet(pciDeviceList *list,
+ int idx)
+{
+ if (idx >= list->count)
+ return NULL;
+ if (idx < 0)
+ return NULL;
+
+ return list->devs[idx];
+}
+
+int
+pciDeviceListCount(pciDeviceList *list)
{
+ return list->count;
+}
+
+pciDevice *
+pciDeviceListSteal(virConnectPtr conn ATTRIBUTE_UNUSED,
+ pciDeviceList *list,
+ pciDevice *dev)
+{
+ pciDevice *ret = NULL;
int i;
for (i = 0; i < list->count; i++) {
list->devs[i]->function != dev->function)
continue;
- pciFreeDevice(conn, list->devs[i]);
+ ret = list->devs[i];
if (i != --list->count)
memmove(&list->devs[i],
break;
}
+ return ret;
+}
+
+void
+pciDeviceListDel(virConnectPtr conn,
+ pciDeviceList *list,
+ pciDevice *dev)
+{
+ pciDevice *ret = pciDeviceListSteal(conn, list, dev);
+ if (ret)
+ pciFreeDevice(conn, ret);
}
pciDevice *