mirror of https://gitee.com/openkylin/libvirt.git
conf: pay attention to bus minSlot/maxSlot when autoassigning PCI addresses
The function that auto-assigns PCI addresses was written with the hardcoded assumptions that any PCI bus would have slots available starting at 1 and ending at 31. This isn't true for many types of controllers (some have a single slot/port at 0, some have slots/ports from 0 to 31). This patch updates that function to remove the hardcoded assumptions. It will properly find/assign addresses for devices that can only connect to pcie-(root|downstream)-port (which have minSlot/maxSlot of 0/0) or a pcie-switch-upstream-port (0/31). It still will not auto-create a new bus of the proper kind for these connections when one doesn't exist, that task is for another day.
This commit is contained in:
parent
be6c35e4ac
commit
d4cf72af17
|
@ -471,55 +471,66 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs,
|
||||||
virDomainPCIConnectFlags flags)
|
virDomainPCIConnectFlags flags)
|
||||||
{
|
{
|
||||||
/* default to starting the search for a free slot from
|
/* default to starting the search for a free slot from
|
||||||
* 0000:00:00.0
|
* the first slot of domain 0 bus 0...
|
||||||
*/
|
*/
|
||||||
virDevicePCIAddress a = { 0, 0, 0, 0, false };
|
virDevicePCIAddress a = { 0, 0, 0, 0, false };
|
||||||
char *addrStr = NULL;
|
char *addrStr = NULL;
|
||||||
|
|
||||||
/* except if this search is for the exact same type of device as
|
|
||||||
* last time, continue the search from the previous match
|
|
||||||
*/
|
|
||||||
if (flags == addrs->lastFlags)
|
|
||||||
a = addrs->lastaddr;
|
|
||||||
|
|
||||||
if (addrs->nbuses == 0) {
|
if (addrs->nbuses == 0) {
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available"));
|
virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available"));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start the search at the last used bus and slot */
|
/* ...unless this search is for the exact same type of device as
|
||||||
for (a.slot++; a.bus < addrs->nbuses; a.bus++) {
|
* last time, then continue the search from the next slot after
|
||||||
|
* the previous match (the "next slot" may possibly be the first
|
||||||
|
* slot of the next bus).
|
||||||
|
*/
|
||||||
|
if (flags == addrs->lastFlags) {
|
||||||
|
a = addrs->lastaddr;
|
||||||
|
if (++a.slot > addrs->buses[a.bus].maxSlot &&
|
||||||
|
++a.bus < addrs->nbuses)
|
||||||
|
a.slot = addrs->buses[a.bus].minSlot;
|
||||||
|
} else {
|
||||||
|
a.slot = addrs->buses[0].minSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (a.bus < addrs->nbuses) {
|
||||||
|
VIR_FREE(addrStr);
|
||||||
if (!(addrStr = virDomainPCIAddressAsString(&a)))
|
if (!(addrStr = virDomainPCIAddressAsString(&a)))
|
||||||
goto error;
|
goto error;
|
||||||
if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
|
if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
|
||||||
addrs->buses[a.bus].flags,
|
addrs->buses[a.bus].flags,
|
||||||
flags, false, false)) {
|
flags, false, false)) {
|
||||||
VIR_FREE(addrStr);
|
|
||||||
VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
|
VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
|
||||||
a.domain, a.bus);
|
a.domain, a.bus);
|
||||||
continue;
|
} else {
|
||||||
}
|
while (a.slot <= addrs->buses[a.bus].maxSlot) {
|
||||||
for (; a.slot <= VIR_PCI_ADDRESS_SLOT_LAST; a.slot++) {
|
if (!virDomainPCIAddressSlotInUse(addrs, &a))
|
||||||
if (!virDomainPCIAddressSlotInUse(addrs, &a))
|
goto success;
|
||||||
goto success;
|
|
||||||
|
|
||||||
VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
|
VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
|
||||||
a.domain, a.bus, a.slot);
|
a.domain, a.bus, a.slot);
|
||||||
|
a.slot++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
a.slot = 1;
|
if (++a.bus < addrs->nbuses)
|
||||||
VIR_FREE(addrStr);
|
a.slot = addrs->buses[a.bus].minSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There were no free slots after the last used one */
|
/* There were no free slots after the last used one */
|
||||||
if (addrs->dryRun) {
|
if (addrs->dryRun) {
|
||||||
/* a is already set to the first new bus and slot 1 */
|
/* a is already set to the first new bus */
|
||||||
if (virDomainPCIAddressSetGrow(addrs, &a, flags) < 0)
|
if (virDomainPCIAddressSetGrow(addrs, &a, flags) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
/* this device will use the first slot of the new bus */
|
||||||
|
a.slot = addrs->buses[a.bus].minSlot;
|
||||||
goto success;
|
goto success;
|
||||||
} else if (flags == addrs->lastFlags) {
|
} else if (flags == addrs->lastFlags) {
|
||||||
/* Check the buses from 0 up to the last used one */
|
/* Check the buses from 0 up to the last used one */
|
||||||
for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) {
|
for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) {
|
||||||
addrStr = NULL;
|
a.slot = addrs->buses[a.bus].minSlot;
|
||||||
|
VIR_FREE(addrStr);
|
||||||
if (!(addrStr = virDomainPCIAddressAsString(&a)))
|
if (!(addrStr = virDomainPCIAddressAsString(&a)))
|
||||||
goto error;
|
goto error;
|
||||||
if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
|
if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
|
||||||
|
@ -527,14 +538,15 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs,
|
||||||
flags, false, false)) {
|
flags, false, false)) {
|
||||||
VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
|
VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
|
||||||
a.domain, a.bus);
|
a.domain, a.bus);
|
||||||
continue;
|
} else {
|
||||||
}
|
while (a.slot <= addrs->buses[a.bus].maxSlot) {
|
||||||
for (a.slot = 1; a.slot <= VIR_PCI_ADDRESS_SLOT_LAST; a.slot++) {
|
if (!virDomainPCIAddressSlotInUse(addrs, &a))
|
||||||
if (!virDomainPCIAddressSlotInUse(addrs, &a))
|
goto success;
|
||||||
goto success;
|
|
||||||
|
|
||||||
VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
|
VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
|
||||||
a.domain, a.bus, a.slot);
|
a.domain, a.bus, a.slot);
|
||||||
|
a.slot++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue