mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 06:50:22 +03:00
pciResetDevice: use inactive devices to determine safe reset
When doing a PCI secondary bus reset, we must be sure that there are no active devices on the same bus segment. The active device tracking is designed to only track host devices that are active in use by guests. This ignores host devices that are actively in use by the host. So the current logic will reset host devices. Switch this logic around and allow sbus reset when we are assigning all devices behind a bridge to the same guest at guest startup or as a result of a single attach-device command. * src/util/pci.h: change signature of pciResetDevice to add an inactive devices list * src/qemu/qemu_driver.c src/xen/xen_driver.c: use (or not) the new functionality of pciResetDevice() depending on the place of use * src/util/pci.c: implement the interface and logic changes
This commit is contained in:
parent
042b208370
commit
46bcdb960d
@ -3107,7 +3107,7 @@ qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
|
||||
* reset them */
|
||||
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
|
||||
pciDevice *dev = pciDeviceListGet(pcidevs, i);
|
||||
if (pciResetDevice(dev, driver->activePciHostdevs) < 0)
|
||||
if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -3253,7 +3253,7 @@ qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
|
||||
|
||||
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
|
||||
pciDevice *dev = pciDeviceListGet(pcidevs, i);
|
||||
if (pciResetDevice(dev, driver->activePciHostdevs) < 0) {
|
||||
if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0) {
|
||||
virErrorPtr err = virGetLastError();
|
||||
VIR_ERROR(_("Failed to reset PCI device: %s"),
|
||||
err ? err->message : _("unknown error"));
|
||||
@ -8995,7 +8995,7 @@ static int qemudDomainDetachHostPciDevice(struct qemud_driver *driver,
|
||||
else {
|
||||
pciDeviceSetManaged(pci, detach->managed);
|
||||
pciDeviceListDel(driver->activePciHostdevs, pci);
|
||||
if (pciResetDevice(pci, driver->activePciHostdevs) < 0)
|
||||
if (pciResetDevice(pci, driver->activePciHostdevs, NULL) < 0)
|
||||
ret = -1;
|
||||
qemudReattachManagedDevice(pci, driver);
|
||||
pciFreeDevice(pci);
|
||||
@ -11620,7 +11620,7 @@ qemudNodeDeviceReset (virNodeDevicePtr dev)
|
||||
|
||||
qemuDriverLock(driver);
|
||||
|
||||
if (pciResetDevice(pci, driver->activePciHostdevs) < 0)
|
||||
if (pciResetDevice(pci, driver->activePciHostdevs, NULL) < 0)
|
||||
goto out;
|
||||
|
||||
ret = 0;
|
||||
|
@ -440,11 +440,11 @@ pciDetectPowerManagementReset(pciDevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Any active devices other than the one supplied on the same domain/bus ? */
|
||||
/* Any active devices on the same domain/bus ? */
|
||||
static int
|
||||
pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data)
|
||||
{
|
||||
pciDeviceList *activeDevs = data;
|
||||
pciDeviceList *inactiveDevs = data;
|
||||
|
||||
/* Different domain, different bus, or simply identical device */
|
||||
if (dev->domain != check->domain ||
|
||||
@ -453,7 +453,8 @@ pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data)
|
||||
dev->function == check->function))
|
||||
return 0;
|
||||
|
||||
if (activeDevs && !pciDeviceListFind(activeDevs, check))
|
||||
/* same bus, but inactive, i.e. about to be assigned to guest */
|
||||
if (inactiveDevs && pciDeviceListFind(inactiveDevs, check))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@ -461,11 +462,11 @@ pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data)
|
||||
|
||||
static pciDevice *
|
||||
pciBusContainsActiveDevices(pciDevice *dev,
|
||||
pciDeviceList *activeDevs)
|
||||
pciDeviceList *inactiveDevs)
|
||||
{
|
||||
pciDevice *active = NULL;
|
||||
if (pciIterDevices(pciSharesBusWithActive,
|
||||
dev, &active, activeDevs) < 0)
|
||||
dev, &active, inactiveDevs) < 0)
|
||||
return NULL;
|
||||
return active;
|
||||
}
|
||||
@ -512,7 +513,7 @@ pciGetParentDevice(pciDevice *dev)
|
||||
*/
|
||||
static int
|
||||
pciTrySecondaryBusReset(pciDevice *dev,
|
||||
pciDeviceList *activeDevs)
|
||||
pciDeviceList *inactiveDevs)
|
||||
{
|
||||
pciDevice *parent, *conflict;
|
||||
uint8_t config_space[PCI_CONF_LEN];
|
||||
@ -524,7 +525,7 @@ pciTrySecondaryBusReset(pciDevice *dev,
|
||||
* In future, we could allow it so long as those devices
|
||||
* are not in use by the host or other guests.
|
||||
*/
|
||||
if ((conflict = pciBusContainsActiveDevices(dev, activeDevs))) {
|
||||
if ((conflict = pciBusContainsActiveDevices(dev, inactiveDevs))) {
|
||||
pciReportError(VIR_ERR_NO_SUPPORT,
|
||||
_("Active %s devices on bus with %s, not doing bus reset"),
|
||||
conflict->name, dev->name);
|
||||
@ -642,7 +643,8 @@ pciInitDevice(pciDevice *dev)
|
||||
|
||||
int
|
||||
pciResetDevice(pciDevice *dev,
|
||||
pciDeviceList *activeDevs)
|
||||
pciDeviceList *activeDevs,
|
||||
pciDeviceList *inactiveDevs)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
@ -670,7 +672,7 @@ pciResetDevice(pciDevice *dev,
|
||||
|
||||
/* Bus reset is not an option with the root bus */
|
||||
if (ret < 0 && dev->bus != 0)
|
||||
ret = pciTrySecondaryBusReset(dev, activeDevs);
|
||||
ret = pciTrySecondaryBusReset(dev, inactiveDevs);
|
||||
|
||||
if (ret < 0) {
|
||||
virErrorPtr err = virGetLastError();
|
||||
|
@ -35,7 +35,8 @@ void pciFreeDevice (pciDevice *dev);
|
||||
int pciDettachDevice (pciDevice *dev, pciDeviceList *activeDevs);
|
||||
int pciReAttachDevice (pciDevice *dev, pciDeviceList *activeDevs);
|
||||
int pciResetDevice (pciDevice *dev,
|
||||
pciDeviceList *activeDevs);
|
||||
pciDeviceList *activeDevs,
|
||||
pciDeviceList *inactiveDevs);
|
||||
void pciDeviceSetManaged(pciDevice *dev,
|
||||
unsigned managed);
|
||||
unsigned pciDeviceGetManaged(pciDevice *dev);
|
||||
|
@ -1892,7 +1892,7 @@ xenUnifiedNodeDeviceReset (virNodeDevicePtr dev)
|
||||
if (!pci)
|
||||
return -1;
|
||||
|
||||
if (pciResetDevice(pci, NULL) < 0)
|
||||
if (pciResetDevice(pci, NULL, NULL) < 0)
|
||||
goto out;
|
||||
|
||||
ret = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user