提交 46bcdb96 编写于 作者: C Chris Wright 提交者: Daniel Veillard

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
上级 042b2083
...@@ -3107,7 +3107,7 @@ qemuPrepareHostdevPCIDevices(struct qemud_driver *driver, ...@@ -3107,7 +3107,7 @@ qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
* reset them */ * reset them */
for (i = 0; i < pciDeviceListCount(pcidevs); i++) { for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDevice *dev = pciDeviceListGet(pcidevs, i); pciDevice *dev = pciDeviceListGet(pcidevs, i);
if (pciResetDevice(dev, driver->activePciHostdevs) < 0) if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0)
goto cleanup; goto cleanup;
} }
...@@ -3253,7 +3253,7 @@ qemuDomainReAttachHostdevDevices(struct qemud_driver *driver, ...@@ -3253,7 +3253,7 @@ qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
for (i = 0; i < pciDeviceListCount(pcidevs); i++) { for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDevice *dev = pciDeviceListGet(pcidevs, i); pciDevice *dev = pciDeviceListGet(pcidevs, i);
if (pciResetDevice(dev, driver->activePciHostdevs) < 0) { if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0) {
virErrorPtr err = virGetLastError(); virErrorPtr err = virGetLastError();
VIR_ERROR(_("Failed to reset PCI device: %s"), VIR_ERROR(_("Failed to reset PCI device: %s"),
err ? err->message : _("unknown error")); err ? err->message : _("unknown error"));
...@@ -8995,7 +8995,7 @@ static int qemudDomainDetachHostPciDevice(struct qemud_driver *driver, ...@@ -8995,7 +8995,7 @@ static int qemudDomainDetachHostPciDevice(struct qemud_driver *driver,
else { else {
pciDeviceSetManaged(pci, detach->managed); pciDeviceSetManaged(pci, detach->managed);
pciDeviceListDel(driver->activePciHostdevs, pci); pciDeviceListDel(driver->activePciHostdevs, pci);
if (pciResetDevice(pci, driver->activePciHostdevs) < 0) if (pciResetDevice(pci, driver->activePciHostdevs, NULL) < 0)
ret = -1; ret = -1;
qemudReattachManagedDevice(pci, driver); qemudReattachManagedDevice(pci, driver);
pciFreeDevice(pci); pciFreeDevice(pci);
...@@ -11620,7 +11620,7 @@ qemudNodeDeviceReset (virNodeDevicePtr dev) ...@@ -11620,7 +11620,7 @@ qemudNodeDeviceReset (virNodeDevicePtr dev)
qemuDriverLock(driver); qemuDriverLock(driver);
if (pciResetDevice(pci, driver->activePciHostdevs) < 0) if (pciResetDevice(pci, driver->activePciHostdevs, NULL) < 0)
goto out; goto out;
ret = 0; ret = 0;
......
...@@ -440,11 +440,11 @@ pciDetectPowerManagementReset(pciDevice *dev) ...@@ -440,11 +440,11 @@ pciDetectPowerManagementReset(pciDevice *dev)
return 0; 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 static int
pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data) pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data)
{ {
pciDeviceList *activeDevs = data; pciDeviceList *inactiveDevs = data;
/* Different domain, different bus, or simply identical device */ /* Different domain, different bus, or simply identical device */
if (dev->domain != check->domain || if (dev->domain != check->domain ||
...@@ -453,7 +453,8 @@ pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data) ...@@ -453,7 +453,8 @@ pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data)
dev->function == check->function)) dev->function == check->function))
return 0; 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 0;
return 1; return 1;
...@@ -461,11 +462,11 @@ pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data) ...@@ -461,11 +462,11 @@ pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data)
static pciDevice * static pciDevice *
pciBusContainsActiveDevices(pciDevice *dev, pciBusContainsActiveDevices(pciDevice *dev,
pciDeviceList *activeDevs) pciDeviceList *inactiveDevs)
{ {
pciDevice *active = NULL; pciDevice *active = NULL;
if (pciIterDevices(pciSharesBusWithActive, if (pciIterDevices(pciSharesBusWithActive,
dev, &active, activeDevs) < 0) dev, &active, inactiveDevs) < 0)
return NULL; return NULL;
return active; return active;
} }
...@@ -512,7 +513,7 @@ pciGetParentDevice(pciDevice *dev) ...@@ -512,7 +513,7 @@ pciGetParentDevice(pciDevice *dev)
*/ */
static int static int
pciTrySecondaryBusReset(pciDevice *dev, pciTrySecondaryBusReset(pciDevice *dev,
pciDeviceList *activeDevs) pciDeviceList *inactiveDevs)
{ {
pciDevice *parent, *conflict; pciDevice *parent, *conflict;
uint8_t config_space[PCI_CONF_LEN]; uint8_t config_space[PCI_CONF_LEN];
...@@ -524,7 +525,7 @@ pciTrySecondaryBusReset(pciDevice *dev, ...@@ -524,7 +525,7 @@ pciTrySecondaryBusReset(pciDevice *dev,
* In future, we could allow it so long as those devices * In future, we could allow it so long as those devices
* are not in use by the host or other guests. * 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, pciReportError(VIR_ERR_NO_SUPPORT,
_("Active %s devices on bus with %s, not doing bus reset"), _("Active %s devices on bus with %s, not doing bus reset"),
conflict->name, dev->name); conflict->name, dev->name);
...@@ -642,7 +643,8 @@ pciInitDevice(pciDevice *dev) ...@@ -642,7 +643,8 @@ pciInitDevice(pciDevice *dev)
int int
pciResetDevice(pciDevice *dev, pciResetDevice(pciDevice *dev,
pciDeviceList *activeDevs) pciDeviceList *activeDevs,
pciDeviceList *inactiveDevs)
{ {
int ret = -1; int ret = -1;
...@@ -670,7 +672,7 @@ pciResetDevice(pciDevice *dev, ...@@ -670,7 +672,7 @@ pciResetDevice(pciDevice *dev,
/* Bus reset is not an option with the root bus */ /* Bus reset is not an option with the root bus */
if (ret < 0 && dev->bus != 0) if (ret < 0 && dev->bus != 0)
ret = pciTrySecondaryBusReset(dev, activeDevs); ret = pciTrySecondaryBusReset(dev, inactiveDevs);
if (ret < 0) { if (ret < 0) {
virErrorPtr err = virGetLastError(); virErrorPtr err = virGetLastError();
......
...@@ -35,7 +35,8 @@ void pciFreeDevice (pciDevice *dev); ...@@ -35,7 +35,8 @@ void pciFreeDevice (pciDevice *dev);
int pciDettachDevice (pciDevice *dev, pciDeviceList *activeDevs); int pciDettachDevice (pciDevice *dev, pciDeviceList *activeDevs);
int pciReAttachDevice (pciDevice *dev, pciDeviceList *activeDevs); int pciReAttachDevice (pciDevice *dev, pciDeviceList *activeDevs);
int pciResetDevice (pciDevice *dev, int pciResetDevice (pciDevice *dev,
pciDeviceList *activeDevs); pciDeviceList *activeDevs,
pciDeviceList *inactiveDevs);
void pciDeviceSetManaged(pciDevice *dev, void pciDeviceSetManaged(pciDevice *dev,
unsigned managed); unsigned managed);
unsigned pciDeviceGetManaged(pciDevice *dev); unsigned pciDeviceGetManaged(pciDevice *dev);
......
...@@ -1892,7 +1892,7 @@ xenUnifiedNodeDeviceReset (virNodeDevicePtr dev) ...@@ -1892,7 +1892,7 @@ xenUnifiedNodeDeviceReset (virNodeDevicePtr dev)
if (!pci) if (!pci)
return -1; return -1;
if (pciResetDevice(pci, NULL) < 0) if (pciResetDevice(pci, NULL, NULL) < 0)
goto out; goto out;
ret = 0; ret = 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册