Allow allocating addresses with non-zero bus numbers. --- src/qemu/qemu_command.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index b50e779..f747cfb 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -954,17 +954,25 @@ cleanup: struct _qemuDomainPCIAddressSet { virHashTablePtr used; virDevicePCIAddress lastaddr; + unsigned int maxbus; }; -static char *qemuPCIAddressAsString(virDevicePCIAddressPtr addr) +static char *qemuPCIAddressAsString(qemuDomainPCIAddressSetPtr addrs, + virDevicePCIAddressPtr addr) { char *str; - if (addr->domain != 0 || - addr->bus != 0) { + if (addr->domain != 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Only PCI domain 0 and bus 0 are available")); + _("Only PCI domain 0 is available")); + return NULL; + } + + if (addr->bus > addrs->maxbus) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Only PCI buses up to %u are available"), + addrs->maxbus); return NULL; } @@ -999,7 +1007,7 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, return 0; } - addr = qemuPCIAddressAsString(&info->addr.pci); + addr = qemuPCIAddressAsString(addrs, &info->addr.pci); if (!addr) goto cleanup; @@ -1028,7 +1036,7 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, unsigned int *func = &tmp_addr.function; for (*func = 1; *func < QEMU_PCI_ADDRESS_LAST_FUNCTION; (*func)++) { - addr = qemuPCIAddressAsString(&tmp_addr); + addr = qemuPCIAddressAsString(addrs, &tmp_addr); if (!addr) goto cleanup; @@ -1148,7 +1156,7 @@ static int qemuDomainPCIAddressCheckSlot(qemuDomainPCIAddressSetPtr addrs, unsigned int *func = &(tmp_addr.function); for (*func = 0; *func < QEMU_PCI_ADDRESS_LAST_FUNCTION; (*func)++) { - str = qemuPCIAddressAsString(&tmp_addr); + str = qemuPCIAddressAsString(addrs, &tmp_addr); if (!str) return -1; @@ -1168,7 +1176,7 @@ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs, { char *str; - str = qemuPCIAddressAsString(addr); + str = qemuPCIAddressAsString(addrs, addr); if (!str) return -1; @@ -1243,7 +1251,7 @@ int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs, char *str; int ret; - str = qemuPCIAddressAsString(addr); + str = qemuPCIAddressAsString(addrs, addr); if (!str) return -1; @@ -1263,7 +1271,7 @@ int qemuDomainPCIAddressReleaseSlot(qemuDomainPCIAddressSetPtr addrs, unsigned int *func = &tmp_addr.function; for (*func = 0; *func < QEMU_PCI_ADDRESS_LAST_FUNCTION; (*func)++) { - str = qemuPCIAddressAsString(&tmp_addr); + str = qemuPCIAddressAsString(addrs, &tmp_addr); if (!str) return -1; @@ -1298,19 +1306,30 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs, virDevicePCIAddress tmp_addr = addrs->lastaddr; int i; char *addr; + bool next_bus = false; tmp_addr.slot++; for (i = 0; i <= QEMU_PCI_ADDRESS_LAST_SLOT; i++, tmp_addr.slot++) { if (QEMU_PCI_ADDRESS_LAST_SLOT < tmp_addr.slot) { + /* Check all the slots in this bus first */ tmp_addr.slot = 0; + next_bus = !next_bus; } - if (!(addr = qemuPCIAddressAsString(&tmp_addr))) + if (!(addr = qemuPCIAddressAsString(addrs, &tmp_addr))) return -1; if (qemuDomainPCIAddressCheckSlot(addrs, &tmp_addr) < 0) { VIR_DEBUG("PCI addr %s already in use", addr); VIR_FREE(addr); + if (i == QEMU_PCI_ADDRESS_LAST_SLOT && next_bus && + tmp_addr.bus < addrs->maxbus) { + /* Move on to the next bus if this one's full */ + i = 0; + tmp_addr.bus++; + tmp_addr.slot = 0; + next_bus = !next_bus; + } continue; } -- 1.7.12.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list