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