virDomainDeviceInfoPtr dev)
{
int ret = 0;
- if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
- ret = qemuDomainPCIAddressReserveAddr(addrs, dev);
- else
+ if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+ /* We do not support hotplug multi-function PCI device now, so we should
+ * reserve the whole slot. The function of the PCI device must be 0.
+ */
+ if (dev->addr.pci.function != 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Only PCI device addresses with function=0"
+ " are supported"));
+ return -1;
+ }
+
+ ret = qemuDomainPCIAddressReserveSlot(addrs, dev->addr.pci.slot);
+ } else {
ret = qemuDomainPCIAddressSetNextAddr(addrs, dev);
+ }
return ret;
}
return qemuDomainPCIAddressReleaseAddr(addrs, &dev);
}
+int qemuDomainPCIAddressReleaseSlot(qemuDomainPCIAddressSetPtr addrs, int slot)
+{
+ virDomainDeviceInfo dev;
+ char *addr;
+ int function;
+ int ret = 0;
+
+ dev.addr.pci.domain = 0;
+ dev.addr.pci.bus = 0;
+ dev.addr.pci.slot = slot;
+
+ for (function = 0; function <= QEMU_PCI_ADDRESS_LAST_FUNCTION; function++) {
+ addr = qemuPCIAddressAsString(&dev);
+ if (!addr)
+ return -1;
+
+ if (!virHashLookup(addrs->used, addr)) {
+ VIR_FREE(addr);
+ continue;
+ }
+
+ VIR_FREE(addr);
+
+ if (qemuDomainPCIAddressReleaseFunction(addrs, slot, function) < 0)
+ ret = -1;
+ }
+
+ return ret;
+}
+
void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
{
if (!addrs)
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
(disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
releaseaddr &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &disk->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ disk->info.addr.pci.slot) < 0)
VIR_WARN("Unable to release PCI address on %s", disk->src);
if (virSecurityManagerRestoreImageLabel(driver->securityManager,
qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
(controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
releaseaddr &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &controller->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ controller->info.addr.pci.slot) < 0)
VIR_WARN("Unable to release PCI address on controller");
VIR_FREE(devstr);
qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
(net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
releaseaddr &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &net->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ net->info.addr.pci.slot) < 0)
VIR_WARN("Unable to release PCI address on NIC");
if (ret != 0)
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
(hostdev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
releaseaddr &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &hostdev->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ hostdev->info.addr.pci.slot) < 0)
VIR_WARN("Unable to release PCI address on host device");
qemuDomainReAttachHostdevDevices(driver, &hostdev, 1);
qemuAuditDisk(vm, detach, NULL, "detach", true);
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ detach->info.addr.pci.slot) < 0)
VIR_WARN("Unable to release PCI address on %s", dev->data.disk->src);
virDomainDiskRemove(vm->def, i);
}
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ detach->info.addr.pci.slot) < 0)
VIR_WARN("Unable to release PCI address on controller");
virDomainControllerDefFree(detach);
qemuAuditNet(vm, detach, NULL, "detach", true);
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ detach->info.addr.pci.slot) < 0)
VIR_WARN("Unable to release PCI address on NIC");
virDomainConfNWFilterTeardown(detach);
}
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ detach->info.addr.pci.slot) < 0)
VIR_WARN("Unable to release PCI address on host device");
if (vm->def->nhostdevs > 1) {