mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 19:32:19 +00:00
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)
|
||||
{
|
||||
/* 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 };
|
||||
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) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Start the search at the last used bus and slot */
|
||||
for (a.slot++; a.bus < addrs->nbuses; a.bus++) {
|
||||
/* ...unless this search is for the exact same type of device as
|
||||
* 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)))
|
||||
goto error;
|
||||
if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
|
||||
addrs->buses[a.bus].flags,
|
||||
flags, false, false)) {
|
||||
VIR_FREE(addrStr);
|
||||
VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
|
||||
a.domain, a.bus);
|
||||
continue;
|
||||
}
|
||||
for (; a.slot <= VIR_PCI_ADDRESS_SLOT_LAST; a.slot++) {
|
||||
if (!virDomainPCIAddressSlotInUse(addrs, &a))
|
||||
goto success;
|
||||
} else {
|
||||
while (a.slot <= addrs->buses[a.bus].maxSlot) {
|
||||
if (!virDomainPCIAddressSlotInUse(addrs, &a))
|
||||
goto success;
|
||||
|
||||
VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
|
||||
a.domain, a.bus, a.slot);
|
||||
VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
|
||||
a.domain, a.bus, a.slot);
|
||||
a.slot++;
|
||||
}
|
||||
}
|
||||
a.slot = 1;
|
||||
VIR_FREE(addrStr);
|
||||
if (++a.bus < addrs->nbuses)
|
||||
a.slot = addrs->buses[a.bus].minSlot;
|
||||
}
|
||||
|
||||
/* There were no free slots after the last used one */
|
||||
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)
|
||||
goto error;
|
||||
/* this device will use the first slot of the new bus */
|
||||
a.slot = addrs->buses[a.bus].minSlot;
|
||||
goto success;
|
||||
} else if (flags == addrs->lastFlags) {
|
||||
/* Check the buses from 0 up to the last used one */
|
||||
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)))
|
||||
goto error;
|
||||
if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
|
||||
@ -527,14 +538,15 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs,
|
||||
flags, false, false)) {
|
||||
VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
|
||||
a.domain, a.bus);
|
||||
continue;
|
||||
}
|
||||
for (a.slot = 1; a.slot <= VIR_PCI_ADDRESS_SLOT_LAST; a.slot++) {
|
||||
if (!virDomainPCIAddressSlotInUse(addrs, &a))
|
||||
goto success;
|
||||
} else {
|
||||
while (a.slot <= addrs->buses[a.bus].maxSlot) {
|
||||
if (!virDomainPCIAddressSlotInUse(addrs, &a))
|
||||
goto success;
|
||||
|
||||
VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
|
||||
a.domain, a.bus, a.slot);
|
||||
VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
|
||||
a.domain, a.bus, a.slot);
|
||||
a.slot++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user